Given a directed and unweighted graph consisting of N vertices and an array arr[] where ith vertex has a directed edge to arr[i]. The task is to find the number of ways to change the direction of edges such that the given graph is acyclic.
Examples:
Input: N = 3, arr[] = {2, 3, 1}
The directed graph form by the given information is:
Output: 6
Explanation:
There are 6 possible ways to change the direction of edges to make graph acyclic:
Approach: The idea is to check whether the Connected Components form a cycle or not.
- If the component is a path, then however we orient the edges we won’t form a cycle.
- If the component has a cycle with N edges, then there are 2N ways to arrange all the edges out of which only 2 ways are going to form a cycle. So there are (2N – 2) ways to change the edges so that graph becomes acyclic.
Steps:
- Using Depth First Search(DFS) traversal find the cycles in the given graph and number of vertices associated with each cycle.
- After DFS traversal, the total number of ways to change the direction of edges is the product of the following:
- Number of ways form by each cycle of X vertices is given by (2X – 2).
- Number of ways form by each path of Y vertices is given by (2Y).
Below is the implementation of the above approach:
// C++ program to count the // number of ways to change // the direction of edges // such that no cycle is // present in the graph #include <bits/stdc++.h> using namespace std;
// Vector cycles[] to store // the cycle with vertices // associated with each cycle vector< int > 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 ;
}
// Recur 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 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<Integer> 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 ;
}
// Recur 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 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
# Recur 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# 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 ;
}
// Recur 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 |
<script> // JavaScript program to count the number // of ways to change the direction // of edges such that no cycle is // present in the graph // Vector cycles[] to store // the cycle with vertices // associated with each cycle let cycles; // Count of cycle let cyclecnt=0; // Function to count the // number of vertices in the // current cycle function DFSUtil(u,arr,vis)
{ cycles[cyclecnt]++;
vis[u] = 3;
// Returns when the same
// initial vertex is found
if (vis[arr[u]] == 3)
{
return ;
}
// Recur for next vertex
DFSUtil(arr[u], arr, vis);
} // DFS traversal to detect // the cycle in graph function DFS(u,arr,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(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 function countWays(arr,N)
{ let i, ans = 1;
// To precompute the power
// of 2
let dp = new Array(N + 1);
for (let i=0;i<dp.length;i++)
{
dp[i]=0;
}
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
let vis = new Array(N + 1);
for (let i=0;i<vis.length;i++)
{
vis[i]=0;
}
// DFS traversal from Node 1
for (i = 1; i <= N; i++)
{
if (vis[i] == 0)
{
// Calling DFS
DFS(i, arr, vis);
}
}
let cnt = N;
// Traverse the cycles array
for (i = 0; i < cycles.length; 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 code let N = 3; let arr=[0, 2, 3, 1]; cycles =[]; // Function to count ways document.write(countWays(arr, N)); // This code is contributed by avanitrachhadiya2155 </script> |
6
Time Complexity : O(V + E)
Auxiliary Space: O(n)