Open In App

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

Last Updated : 03 Apr, 2023
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)



Similar Reads

Ways to Remove Edges from a Complete Graph to make Odd Edges
Given a complete graph with N vertices, the task is to count the number of ways to remove edges such that the resulting graph has odd number of edges. Examples: Input: N = 3 Output: 4 The initial graph has 3 edges as it is a complete graph. We can remove edges (1, 2) and (1, 3) or (1, 2) and (2, 3) or (1, 3) and (2, 3) or we do not remove any of th
4 min read
Assign directions to edges so that the directed graph remains acyclic
Given a graph with both directed and undirected edges. It is given that the directed edges don't form cycle. How to assign directions to undirected edges so that the graph (with all directed edges) remains acyclic even after the assignment? For example, in the below graph, blue edges don't have directions. We strongly recommend to minimize your bro
1 min read
Minimum number of edges required to be removed from an Undirected Graph to make it acyclic
Given an undirected graph consisting of N nodes containing values from the range [1, N] and M edges in a matrix Edges[][], the task is to determine the minimum number of edges required to be removed such that the resulting graph does not contain any cycle. Examples: Input: N = 3, M = 3, edges[][] = [[1, 2], [2, 3], [3, 1]] Output: 1Explanation:Remo
8 min read
Maximum Bitwise XOR of node values of an Acyclic Graph made up of N given vertices using M edges
Given N nodes valued by [1, N], an array arr[] consisting of N positive integers such that the ith node ( 1-based indexing ) has the value arr[i] and an integer M, the task is to find the maximum Bitwise XOR of node values of an acyclic graph formed by M edges. Examples: Input: arr[]= {1, 2, 3, 4}, M = 2Output: 7Explanation:Acyclic graphs having M(
7 min read
Pendant Vertices, Non-Pendant Vertices, Pendant Edges and Non-Pendant Edges in Graph
Pre-requisites: Handshaking theorem. Pendant Vertices Let G be a graph, A vertex v of G is called a pendant vertex if and only if v has degree 1. In other words, pendant vertices are the vertices that have degree 1, also called pendant vertex. Note: Degree = number of edges connected to a vertex In the case of trees, a pendant vertex is known as a
7 min read
Maximum number of edges that N-vertex graph can have such that graph is Triangle free | Mantel's Theorem
Given a number N which is the number of nodes in a graph, the task is to find the maximum number of edges that N-vertex graph can have such that graph is triangle-free (which means there should not be any three edges A, B, C in the graph such that A is connected to B, B is connected to C and C is connected to A). The graph cannot contain a self-loo
4 min read
Connect a graph by M edges such that the graph does not contain any cycle and Bitwise AND of connected vertices is maximum
Given an array arr[] consisting of values of N vertices of an initially unconnected Graph and an integer M, the task is to connect some vertices of the graph with exactly M edges, forming only one connected component, such that no cycle can be formed and Bitwise AND of the connected vertices is maximum possible. Examples: Input: arr[] = {1, 2, 3, 4
9 min read
Count distinct ways to replace array elements such that product of the array becomes even
Given an array arr[] consisting of N odd integers, the task is to count the different number of ways to make the product of all array elements even, by repeatedly changing any set of elements to any values. Since the count can be very large, print it to modulo 109 + 7. Examples: Input: arr[] = {1, 3}Output: 3Explanation: All possible ways to make t
6 min read
Check if XOR of each connected component becomes equal after removing atmost P edges
Given, a Tree with N nodes, and an integer P, the task is to remove at edges in range [1, P) and find the XOR of nodes for every connected component formed. If node's values come out to be equal for all connected components formed, Print "YES" else "NO". Examples: Input: N = 5, P = 5, Edges[][]={ { 1, 2 }, { 2, 3 }, { 1, 4 }, { 4, 5 }}, nodes[] = {
20 min read
Count permutations of all integers upto N that can form an acyclic graph based on given conditions
Given an integer N, the task is to find the number of permutations of integers from the range [1, N] that can form an acyclic graph according to the following conditions: For every 1 ? i ? N, find the largest j such that 1 ? j &lt; i and A[j] &gt; A[i], and add an undirected edge between node i and node j.For every 1 ? i ? N, find the smallest j su
4 min read