Skip to content
Related Articles
Open in App
Not now

Related Articles

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

Improve Article
Save Article
Like Article
  • Difficulty Level : Expert
  • Last Updated : 30 Jan, 2023
Improve Article
Save Article
Like Article

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




<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;
    }
    
    // Recurr 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)


My Personal Notes arrow_drop_up
Like Article
Save Article
Related Articles

Start Your Coding Journey Now!