给定一个由N个顶点和一个数组arr[]组成的有向和未加权图,其中第 i 个顶点具有到arr[i] 的有向边。任务是找到改变边方向的方法的数量,使得给定的图是无环的。
例子:
Input: N = 3, arr[] = {2, 3, 1}
The directed graph form by the given infromation is:
Output: 6
Explanation:
There are 6 possible ways to change the direction of edges to make graph acyclic:
方法:想法是检查Connected Components是否形成循环。
- 如果组件是路径,那么我们将边缘定向,我们不会形成循环。
- 如果组件有一个带有 N 条边的环,那么有2 N种方式可以排列所有边,其中只有 2 种方式会形成一个环。所以有(2 N – 2)种方法可以改变边,使图变为无环。
步骤:
- 使用深度优先搜索 (DFS) 遍历查找给定图中的循环以及与每个循环关联的顶点数。
- 经过 DFS 遍历后,改变边方向的方式总数为以下乘积:
- X顶点的每个循环形成的路数由(2 X – 2) 给出。
- Y顶点的每条路径形成的路数由(2 Y ) 给出。
下面是上述方法的实现:
C++
// C++ program to count the
// number of ways to change
// the direction of edges
// such that no cycle is
// present in the graph
#include
using namespace std;
// Vector cycles[] to store
// the cycle with vertices
// associated with each cycle
vector cycles;
// Count of cycle
int cyclecnt;
// Function to count the
// number of vertices in the
// current cycle
void DFSUtil(int u, int arr[], int vis[])
{
cycles[cyclecnt]++;
vis[u] = 3;
// Returns when the same
// initial vertex is found
if (vis[arr[u]] == 3) {
return;
}
// Recurr for next vertex
DFSUtil(arr[u], arr, vis);
}
// DFS traversal to detect
// the cycle in graph
void DFS(int u, int arr[], int vis[])
{
// Marke vis[u] to 2 to
// check for any cycle form
vis[u] = 2;
// If the vertex arr[u]
// is not visited
if (vis[arr[u]] == 0) {
// Call DFS
DFS(arr[u], arr, vis);
}
// If current node is
// processed
else if (vis[arr[u]] == 1) {
vis[u] = 1;
return;
}
// Cycle found, call DFSUtil
// to count the number of
// vertices in the current
// cycle
else {
cycles.push_back(0);
// Count number of
// vertices in cycle
DFSUtil(u, arr, vis);
cyclecnt++;
}
// Current Node is processed
vis[u] = 1;
}
// Function to count the
// number of ways
int countWays(int arr[], int N)
{
int i, ans = 1;
// To precompute the power
// of 2
int dp[N + 1];
dp[0] = 1;
// Storing power of 2
for (int i = 1; i <= N; i++) {
dp[i] = (dp[i - 1] * 2);
}
// Array vis[] created for
// DFS traversal
int vis[N + 1] = { 0 };
// DFS traversal from Node 1
for (int i = 1; i <= N; i++) {
if (vis[i] == 0) {
// Calling DFS
DFS(i, arr, vis);
}
}
int cnt = N;
// Traverse the cycles array
for (i = 0; i < cycles.size(); i++) {
// Remove the vertices
// which are part of a
// cycle
cnt -= cycles[i];
// Count form by number
// vertices form cycle
ans *= dp[cycles[i]] - 2;
}
// Count form by number of
// vertices not forming
// cycle
ans = (ans * dp[cnt]);
return ans;
}
// Driver's Code
int main()
{
int N = 3;
int arr[] = { 0, 2, 3, 1 };
// Function to count ways
cout << countWays(arr, N);
return 0;
}
Java
// Java program to count the number
// of ways to change the direction
// of edges such that no cycle is
// present in the graph
import java.util.*;
import java.lang.*;
import java.io.*;
class GFG{
// Vector cycles[] to store
// the cycle with vertices
// associated with each cycle
static ArrayList cycles;
// Count of cycle
static int cyclecnt;
// Function to count the
// number of vertices in the
// current cycle
static void DFSUtil(int u, int arr[],
int vis[])
{
cycles.set(cyclecnt,
cycles.get(cyclecnt) + 1);
vis[u] = 3;
// Returns when the same
// initial vertex is found
if (vis[arr[u]] == 3)
{
return;
}
// Recurr for next vertex
DFSUtil(arr[u], arr, vis);
}
// DFS traversal to detect
// the cycle in graph
static void DFS(int u, int arr[], int vis[])
{
// Marke vis[u] to 2 to
// check for any cycle form
vis[u] = 2;
// If the vertex arr[u]
// is not visited
if (vis[arr[u]] == 0)
{
// Call DFS
DFS(arr[u], arr, vis);
}
// If current node is
// processed
else if (vis[arr[u]] == 1)
{
vis[u] = 1;
return;
}
// Cycle found, call DFSUtil
// to count the number of
// vertices in the current
// cycle
else
{
cycles.add(0);
// Count number of
// vertices in cycle
DFSUtil(u, arr, vis);
cyclecnt++;
}
// Current Node is processed
vis[u] = 1;
}
// Function to count the
// number of ways
static int countWays(int arr[], int N)
{
int i, ans = 1;
// To precompute the power
// of 2
int[] dp = new int[N + 1];
dp[0] = 1;
// Storing power of 2
for(i = 1; i <= N; i++)
{
dp[i] = (dp[i - 1] * 2);
}
// Array vis[] created for
// DFS traversal
int[] vis = new int[N + 1];
// DFS traversal from Node 1
for(i = 1; i <= N; i++)
{
if (vis[i] == 0)
{
// Calling DFS
DFS(i, arr, vis);
}
}
int cnt = N;
// Traverse the cycles array
for(i = 0; i < cycles.size(); i++)
{
// Remove the vertices
// which are part of a
// cycle
cnt -= cycles.get(i);
// Count form by number
// vertices form cycle
ans *= dp[cycles.get(i)] - 2;
}
// Count form by number of
// vertices not forming
// cycle
ans = (ans * dp[cnt]);
return ans;
}
// Driver code
public static void main(String[] args)
{
int N = 3;
int arr[] = { 0, 2, 3, 1 };
cycles = new ArrayList<>();
// Function to count ways
System.out.println(countWays(arr, N));
}
}
// This code is contributed by offbeat
Python3
# Python3 program to count the
# number of ways to change
# the direction of edges
# such that no cycle is
# present in the graph
# List cycles[] to store
# the cycle with vertices
# associated with each cycle
cycles = []
# Function to count the
# number of vertices in the
# current cycle
def DFSUtil(u, arr, vis, cyclecnt):
cycles[cyclecnt] += 1
vis[u] = 3
# Returns when the same
# initial vertex is found
if (vis[arr[u]] == 3) :
return
# Recurr for next vertex
DFSUtil(arr[u], arr, vis, cyclecnt)
# DFS traversal to detect
# the cycle in graph
def DFS( u, arr, vis, cyclecnt):
# Marke vis[u] to 2 to
# check for any cycle form
vis[u] = 2
# If the vertex arr[u]
# is not visited
if (vis[arr[u]] == 0) :
# Call DFS
DFS(arr[u], arr, vis, cyclecnt)
# If current node is
# processed
elif (vis[arr[u]] == 1):
vis[u] = 1
return
# Cycle found, call DFSUtil
# to count the number of
# vertices in the current
# cycle
else :
cycles.append(0)
# Count number of
# vertices in cycle
DFSUtil(u, arr, vis,cyclecnt)
cyclecnt += 1
# Current Node is processed
vis[u] = 1
# Function to count the
# number of ways
def countWays(arr, N,cyclecnt):
ans = 1
# To precompute the power
# of 2
dp = [0]*(N + 1)
dp[0] = 1
# Storing power of 2
for i in range(1, N + 1):
dp[i] = (dp[i - 1] * 2)
# Array vis[] created for
# DFS traversal
vis = [0]*(N + 1)
# DFS traversal from Node 1
for i in range(1, N + 1) :
if (vis[i] == 0) :
# Calling DFS
DFS(i, arr, vis, cyclecnt)
cnt = N
# Traverse the cycles array
for i in range(len(cycles)) :
# Remove the vertices
# which are part of a
# cycle
cnt -= cycles[i]
# Count form by number
# vertices form cycle
ans *= dp[cycles[i]] - 2
# Count form by number of
# vertices not forming
# cycle
ans = (ans * dp[cnt])
return ans
# Driver's Code
if __name__ == "__main__":
N = 3
cyclecnt = 0
arr = [ 0, 2, 3, 1 ]
# Function to count ways
print(countWays(arr, N,cyclecnt))
# This code is contributed by chitranayal
C#
// C# program to count the number
// of ways to change the direction
// of edges such that no cycle is
// present in the graph
using System;
using System.Collections;
using System.Collections.Generic;
class GFG{
// Vector cycles[] to store
// the cycle with vertices
// associated with each cycle
static ArrayList cycles;
// Count of cycle
static int cyclecnt;
// Function to count the
// number of vertices in the
// current cycle
static void DFSUtil(int u, int []arr,
int []vis)
{
cycles[cyclecnt] = (int)cycles[cyclecnt] + 1;
vis[u] = 3;
// Returns when the same
// initial vertex is found
if (vis[arr[u]] == 3)
{
return;
}
// Recurr for next vertex
DFSUtil(arr[u], arr, vis);
}
// DFS traversal to detect
// the cycle in graph
static void DFS(int u, int []arr, int []vis)
{
// Marke vis[u] to 2 to
// check for any cycle form
vis[u] = 2;
// If the vertex arr[u]
// is not visited
if (vis[arr[u]] == 0)
{
// Call DFS
DFS(arr[u], arr, vis);
}
// If current node is
// processed
else if (vis[arr[u]] == 1)
{
vis[u] = 1;
return;
}
// Cycle found, call DFSUtil
// to count the number of
// vertices in the current
// cycle
else
{
cycles.Add(0);
// Count number of
// vertices in cycle
DFSUtil(u, arr, vis);
cyclecnt++;
}
// Current Node is processed
vis[u] = 1;
}
// Function to count the
// number of ways
static int countWays(int []arr, int N)
{
int i, ans = 1;
// To precompute the power
// of 2
int[] dp = new int[N + 1];
dp[0] = 1;
// Storing power of 2
for(i = 1; i <= N; i++)
{
dp[i] = (dp[i - 1] * 2);
}
// Array vis[] created for
// DFS traversal
int[] vis = new int[N + 1];
// DFS traversal from Node 1
for(i = 1; i <= N; i++)
{
if (vis[i] == 0)
{
// Calling DFS
DFS(i, arr, vis);
}
}
int cnt = N;
// Traverse the cycles array
for(i = 0; i < cycles.Count; i++)
{
// Remove the vertices
// which are part of a
// cycle
cnt -= (int)cycles[i];
// Count form by number
// vertices form cycle
ans *= dp[(int)cycles[i]] - 2;
}
// Count form by number of
// vertices not forming
// cycle
ans = (ans * dp[cnt]);
return ans;
}
// Driver code
public static void Main(string[] args)
{
int N = 3;
int []arr = new int[]{ 0, 2, 3, 1 };
cycles = new ArrayList();
// Function to count ways
Console.Write(countWays(arr, N));
}
}
// This code is contributed by rutvik_56
Javascript
输出:
6
时间复杂度: O(V + E)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。