Open In App

Count ways to change direction of edges such that graph becomes acyclic

Improve
Improve
Like Article
Like
Save
Share
Report

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: 
 

Directed Graph

Output:
Explanation: 
There are 6 possible ways to change the direction of edges to make graph acyclic: 
 

Way1

 

Way2

 

Way3

 

Way4

 

Way5

 

Way6

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++




// 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




// 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




# 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#




// 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


Javascript




<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>


Output: 

6

 

Time Complexity : O(V + E)
Auxiliary Space: O(n)



Last Updated : 03 Apr, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads