Given a directed graph with n nodes from 0 to n-1, a 2d array edges[][] where edges[i] = [ui, vi] represents a directed edge going from node ui to node vi . The graph would form a tree if its edges were bi-directional, the task is to find the minimum edge direction reversals required for each node such that there is a directed path from that node to all other nodes. Return the array where ith index represents the minimum edge reversals required from that particular to reach all other nodes.
For node 0 the edge between the 1 and 2 should be reverse to reach every node so 2.
For node 1 already all nodes are reachable from node 1 so 0.
For node 2 the edge between the 2 and 1 should be reversed to reach every node so 1.
Naive Approach: The basic way to solve the problem is as follows:
In this approach the problem can be solve by counting the number of edges to reversed for each node , first for a edge u->v the reversal required is 0 but for from v to u it requires 1 reversal during initializing the graph for each mark the reversal for opposite direction to 1 and the same direction to 0 using a dp array , then do DFS for each node to all other nodes and then keep adding the dp[node] then the dp array will be our answer.
Time Complexity: O(n*n) where n is the number of nodes Auxiliary Space: O(n) where n is the number of nodes
Efficient approach: To solve the problem follow the below idea:
In this approach we only compute the total reversals required for one node to reach all other nodes by maintaing another array also for number of reversals required to reach some node x from the root node and also maintaining another array for storing the depth of each node from root node. From only one DFS call we maintain these arrays and the total reversals required for the root node reach all the nodes.
Using the depth we can find the reversals required in reverse direction for example the number of revesals from node x to node y is m ,the reversals required for going from node y to node x is depth from root - m. Using this logic we can compute the reversals required to discover all other nodes using one DFS only for root node and maintaing the depth and reversal required to reach all other nodes.
Like the final equation to find the reversals required to reach node x to all other nodes is :
Suppose the reversals required to for root node to all other nodes is totalReversals , the depth of node x from root node is d and number of reversals is r .
Since we know using the DFS we have computed the totalReversals from root node , suppose from any node x using (d-r) reversals we can reach root node from root node we can reach all other nodes by using the totalReversals - r (that is excluding the number of reversals required to reach node x )
So the reversals for any node x to reach all other nodes , the answer be like :
depth - reversals required to reach node x from root + total reversals for root node - number of reversals to reach node x from root
Follow these steps to solve the above approach:
Initialize the res array to store the result, depth array to store the depth of root i from the root node, visited array to keep track of visited nodes,edgeRev array to keep track of number of reversals required to reach node i from the root node, graph , and totalReversals to 0.
Construct the graph along with the reversal count which is 0 for u-> v and 1 for v-> u.
Start the DFS from the node 0 and compute the depth, edgeRev arrays and the totalReversals required for node 0 to reach all the node.
After the DFS ,assign the total reversals to the root node 0.
For each node compute the total reversals by iterating from 0 to n.
Count the reversals from the node i to root, Count the reversals from the root i to remaining nodes and add them and assing to res[i].
Return the result.
Implementation of the above approach:
C++
// C++ code for the above appraoch:#include<bits/stdc++.h>usingnamespacestd;// Function to perform DFS on root nodevoidDFS(intnode,intpar,unordered_map<int,vector<pair<int,int>>>graph,vector<bool>&visited,vector<int>&edgeRev,intd,vector<int>&depth,int&totalReversals){// Mark the node as vsisitedvisited[node]=true;// Assign the depth of the nodedepth[node]=d;// Iterate throgh the child and// explore the childfor(autochild:graph[node]){if(!visited[child.first]){// Sum up the reversal required to// reach the child from the root nodeedgeRev[child.first]=edgeRev[node]+child.second;// Add the reversals until nowtotalReversals+=child.second;// Perform the DFS on teh childDFS(child.first,node,graph,visited,edgeRev,d+1,depth,totalReversals);}}}// Function to find the minimum edge reversals// required for each node to raech all other nodesvector<int>minimumEdgeReversals(intn,vector<vector<int>>&edges){// Initialize the res array to store the// result, depth array to store the depth of// root i from the root node, visited array// to keep track of visited nodes, edgeRev// array to keep track of number of reversals// required to reach node i from the root// node, graph, and totalReversals to 0.vector<int>res(n,0);vector<int>depth(n,0);vector<bool>visited(n,false);vector<int>edgeRev(n,0);inttotalReversals=0;unordered_map<int,vector<pair<int,int>>>graph;// Start from the node 0intstartNode=0;// Construct the graph along with the// reversal count which is 0 for// u-> v and 1 for v-> u.for(autoedge:edges){intu=edge[0],v=edge[1];graph[u].push_back({v,0});graph[v].push_back({u,1});}// Start the DFS from the node 0.DFS(startNode,-1,graph,visited,edgeRev,0,depth,totalReversals);// Assign the total reversals to// the root node 0.res[startNode]=totalReversals;// For each node compute the total reversalsfor(inti=0;i<n;i++){if(i==startNode)continue;// Count the reversals from the// node i to rootintxToRootRev=depth[i]-edgeRev[i];// Count the reversals from the root// i to remaining nodesintrootToRem=totalReversals-edgeRev[i];// Add the sumres[i]=xToRootRev+rootToRem;}// Return the resultreturnres;}// Driver codeintmain(){intn=4;vector<vector<int>>edges={{2,0},{2,1},{1,3}};vector<int>res=minimumEdgeReversals(n,edges);for(inti=0;i<res.size();i++){cout<<res[i]<<" ";}return0;}
Java
importjava.util.*;classEdgeReversals{// Function to perform DFS on the root nodestaticvoidDFS(intnode,intpar,Map<Integer,List<Pair<Integer,Integer>>>graph,boolean[]visited,int[]edgeRev,intd,int[]depth,int[]totalReversals){// Mark the node as visitedvisited[node]=true;// Assign the depth of the nodedepth[node]=d;// Iterate through the child and// explore the childfor(Pair<Integer,Integer>child:graph.get(node)){if(!visited[child.getKey()]){// Sum up the reversal required to// reach the child from the root nodeedgeRev[child.getKey()]=edgeRev[node]+child.getValue();// Add the reversals until nowtotalReversals[0]+=child.getValue();// Perform DFS on the childDFS(child.getKey(),node,graph,visited,edgeRev,d+1,depth,totalReversals);}}}// Function to find the minimum edge reversals// required for each node to reach all other nodesstaticint[]minimumEdgeReversals(intn,int[][]edges){// Initialize the res array to store the// result, depth array to store the depth of// root i from the root node, visited array// to keep track of visited nodes, edgeRev// array to keep track of the number of reversals// required to reach node i from the root// node, graph, and totalReversals to 0.int[]res=newint[n];int[]depth=newint[n];boolean[]visited=newboolean[n];int[]edgeRev=newint[n];int[]totalReversals={0};Map<Integer,List<Pair<Integer,Integer>>>graph=newHashMap<>();// Start from the node 0intstartNode=0;// Construct the graph along with the// reversal count which is 0 for// u -> v and 1 for v -> u.for(int[]edge:edges){intu=edge[0],v=edge[1];graph.computeIfAbsent(u,k->newArrayList<>()).add(newPair<>(v,0));graph.computeIfAbsent(v,k->newArrayList<>()).add(newPair<>(u,1));}// Start the DFS from the node 0.DFS(startNode,-1,graph,visited,edgeRev,0,depth,totalReversals);// Assign the total reversals to// the root node 0.res[startNode]=totalReversals[0];// For each node, compute the total reversalsfor(inti=0;i<n;i++){if(i==startNode)continue;// Count the reversals from the// node i to the rootintxToRootRev=depth[i]-edgeRev[i];// Count the reversals from the root// i to remaining nodesintrootToRem=totalReversals[0]-edgeRev[i];// Add the sumres[i]=xToRootRev+rootToRem;}// Return the resultreturnres;}// Driver codepublicstaticvoidmain(String[]args){intn=4;int[][]edges={{2,0},{2,1},{1,3}};int[]res=minimumEdgeReversals(n,edges);for(inti=0;i<res.length;i++){System.out.print(res[i]+" ");}}staticclassPair<K,V>{privatefinalKkey;privatefinalVvalue;publicPair(Kkey,Vvalue){this.key=key;this.value=value;}publicKgetKey(){returnkey;}publicVgetValue(){returnvalue;}}}// This code is contributed by rambabuguphka
Python3
fromcollectionsimportdefaultdict# Function to perform Depth-First Search (DFS) on the root nodedefDFS(node,par,graph,visited,edgeRev,d,depth,totalReversals):visited[node]=Truedepth[node]=d# Traverse through the children of the current nodeforchild,valueingraph[node]:ifnotvisited[child]:# Update the reversal count for the child nodeedgeRev[child]=edgeRev[node]+valuetotalReversals[0]+=value# Perform DFS on the child nodeDFS(child,node,graph,visited,edgeRev,d+1,depth,totalReversals)# Function to find the minimum edge reversals required for each nodedefminimumEdgeReversals(n,edges):res=[0]*ndepth=[0]*nvisited=[False]*nedgeRev=[0]*ntotalReversals=[0]graph=defaultdict(list)# Create an adjacency list representation using defaultdictstartNode=0# Define the starting node for traversal# Create the graph representation from the given edgesforedgeinedges:u,v=edgegraph[u].append((v,0))graph[v].append((u,1))# Perform DFS starting from the start nodeDFS(startNode,-1,graph,visited,edgeRev,0,depth,totalReversals)res[startNode]=totalReversals[0]# Set the total reversals for the starting node# Calculate the minimum edge reversals for each nodeforiinrange(n):ifi==startNode:continuexToRootRev=depth[i]-edgeRev[i]rootToRem=totalReversals[0]-edgeRev[i]res[i]=xToRootRev+rootToRem# Compute the total reversals required for each nodereturnres# Return the result array containing minimum edge reversals for each node# Driver codeif__name__=="__main__":n=4edges=[[2,0],[2,1],[1,3]]res=minimumEdgeReversals(n,edges)# Display the minimum edge reversals for each nodeforiinrange(len(res)):print(res[i],end=" ")
C#
usingSystem;usingSystem.Collections.Generic;publicclassGFG{// Function to perform DFS on root nodestaticvoidDFS(intnode,intpar,Dictionary<int,List<KeyValuePair<int,int>>>graph,bool[]visited,int[]edgeRev,intd,int[]depth,refinttotalReversals){// Mark the node as visitedvisited[node]=true;// Assign the depth of the nodedepth[node]=d;// Iterate through the children and explore themforeach(varchildingraph[node]){if(!visited[child.Key]){// Sum up the reversal required to reach the// child from the root nodeedgeRev[child.Key]=edgeRev[node]+child.Value;// Add the reversals until nowtotalReversals+=child.Value;// Perform the DFS on the childDFS(child.Key,node,graph,visited,edgeRev,d+1,depth,reftotalReversals);}}}// Function to find the minimum edge reversals// required for each node to reach all other nodesstaticList<int>MinimumEdgeReversals(intn,List<List<int>>edges){// Initialize the res array to store the result,// depth array to store the depth of root i from the// root node, visited array to keep track of visited// nodes, edgeRev array to keep track of number of// reversals required to reach node i from the root// node, graph, and totalReversals to 0.List<int>res=newList<int>(newint[n]);int[]depth=newint[n];bool[]visited=newbool[n];int[]edgeRev=newint[n];inttotalReversals=0;Dictionary<int,List<KeyValuePair<int,int>>>graph=newDictionary<int,List<KeyValuePair<int,int>>>();// Start from the node 0intstartNode=0;// Construct the graph along with the// reversal count which is 0 for u->v and 1 for// v->u.foreach(varedgeinedges){intu=edge[0],v=edge[1];if(!graph.ContainsKey(u))graph[u]=newList<KeyValuePair<int,int>>();if(!graph.ContainsKey(v))graph[v]=newList<KeyValuePair<int,int>>();graph[u].Add(newKeyValuePair<int,int>(v,0));graph[v].Add(newKeyValuePair<int,int>(u,1));}// Start the DFS from the node 0DFS(startNode,-1,graph,visited,edgeRev,0,depth,reftotalReversals);// Assign the total reversals to the root node 0res[startNode]=totalReversals;// For each node compute the total reversalsfor(inti=0;i<n;i++){if(i==startNode)continue;// Count the reversals from the node i to rootintxToRootRev=depth[i]-edgeRev[i];// Count the reversals from the root i to// remaining nodesintrootToRem=totalReversals-edgeRev[i];// Add the sumres[i]=xToRootRev+rootToRem;}// Return the resultreturnres;}// Driver codestaticpublicvoidMain(){intn=4;List<List<int>>edges=newList<List<int>>(){newList<int>(){2,0},newList<int>(){2,1},newList<int>(){1,3}};List<int>res=MinimumEdgeReversals(n,edges);foreach(varvalinres){Console.Write(val+" ");}}}
JavaScript
// javaScript code for the above approach// Function to perform DFS on root nodefunctionDFS(node,par,graph,visited,edgeRev,d,depth,totalReversals){visited[node]=true;depth[node]=d;if(graph.has(node)){for(const[child,val]ofgraph.get(node)){if(!visited[child]){edgeRev[child]=edgeRev[node]+val;totalReversals[0]+=val;DFS(child,node,graph,visited,edgeRev,d+1,depth,totalReversals);}}}}// Function to find the minimum edge reversals// required for each node to raech all other nodesfunctionminimumEdgeReversals(n,edges){// Initialize the res array to store the// result, depth array to store the depth of// root i from the root node, visited array// to keep track of visited nodes, edgeRev// array to keep track of number of reversals// required to reach node i from the root// node, graph, and totalReversals to 0.constres=Array(n).fill(0);constdepth=Array(n).fill(0);constvisited=Array(n).fill(false);constedgeRev=Array(n).fill(0);consttotalReversals=[0];constgraph=newMap();conststartNode=0;// Construct the graph along with the// reversal count which is 0 for// u-> v and 1 for v-> u.for(const[u,v]ofedges){if(!graph.has(u))graph.set(u,[]);if(!graph.has(v))graph.set(v,[]);graph.get(u).push([v,0]);graph.get(v).push([u,1]);}DFS(startNode,-1,graph,visited,edgeRev,0,depth,totalReversals);// Assign the total reversals to// the root node 0.res[startNode]=totalReversals[0];// For each node compute the total reversalsfor(leti=0;i<n;i++){if(i===startNode)continue;// Count the reversals from the// node i to rootconstxToRootRev=depth[i]-edgeRev[i];// Count the reversals from the root// i to remaining nodesconstrootToRem=totalReversals[0]-edgeRev[i];// add the sumres[i]=xToRootRev+rootToRem;}// return resultreturnres;}// Driver Codeconstn=4;constedges=[[2,0],[2,1],[1,3]];constres=minimumEdgeReversals(n,edges);console.log(res.join(" "));
Output
1 1 0 2
Time Complexity: O(n) where n is the number of nodes. Auxiliary Space: O(n) where n is the number of nodes.