Convert undirected connected graph to strongly connected directed graph
Given an undirected graph of N vertices and M edges, the task is to assign directions to the given M Edges such that the graph becomes Strongly Connected Components. If a graph cannot be converted into Strongly Connected Components then print “-1”.
Examples:
Input: N = 5, Edges[][] = { { 0, 1 }, { 0, 2 }, { 1, 2 }, { 1, 4 }, { 2, 3 }, { 3, 4 } }
Output:
0->1
2->0
4->1
3->4
2->3
1->2
Explanation:
Below is the assigned edges to the above undirected graph:
Input: N = 5, Edges[][] = { { 0, 1 }, { 0, 2 }, { 1, 3 }, { 2, 3 }, { 3, 4 } }
Output: -1
Explanation:
Below is the graph for the above information:
Since there is a bridge present in the above-undirected graph. Therefore, this graph can’t be converted into SCCs.
Approach: We know that in any directed graph is said to be in Strongly Connected Components(SCCs) if all the vertices of the graph are a part of some cycle. The given undirected graph doesn’t form SCCs if and only if the graph contains any bridges in it. Below are the steps:
- We will use an array mark[] to store the visited node during DFS Traversal, order[] to store the index number of the visited node, and bridge_detect[] to store any bridge present in the given graph.
- Start the DFS Traversal from vertex 1.
- Traverse the Adjacency list of current Node and do the following:
- If any edges are traverse again while any DFS call then ignore that edges.
- If the order of child Node(Node u) is greater than the order of parent node(node v), then ignore this current edges as Edges(v, u) is already processed.
- If any Back Edge is found then update the Bridge Edges of the current parent node(node v) as:
bridge_detect[v] = min(order[u], bridge_detect[v]);
- Else do the DFS Traversal for the current child node and repeat step 3 for the current node.
- Update the bridges detect after DFS call for the current node as:
bridge_detect[v] = min(bridge_detect[u], bridge_detect[v])
- Store the current pair of Edges(v, u) as directed Edges from Node v to Node u in an array of pairs(say arr[][]).
- If there is any bridge present in the given graph then print “-1”.
- Else print the directed Edges stored in arr[][].
Below is the implementation of the above approach:
C++
// C++ program for the above approach #include <bits/stdc++.h> using namespace std; // To store the assigned Edges vector<pair< int , int > > ans; // Flag variable to check Bridges int flag = 1; // Function to implement DFS Traversal int dfs(vector< int > adj[], int * order, int * bridge_detect, bool * mark, int v, int l) { // Mark the current node as visited mark[v] = 1; // Update the order of node v order[v] = order[l] + 1; // Update the bridge_detect for node v bridge_detect[v] = order[v]; // Traverse the adjacency list of // Node v for ( int i = 0; i < adj[v].size(); i++) { int u = adj[v][i]; // Ignores if same edge is traversed if (u == l) { continue ; } // Ignores the edge u --> v as // v --> u is already processed if (order[v] < order[u]) { continue ; } // Finds a back Edges, cycle present if (mark[u]) { // Update the bridge_detect[v] bridge_detect[v] = min(order[u], bridge_detect[v]); } // Else DFS traversal for current // node in the adjacency list else { dfs(adj, order, bridge_detect, mark, u, v); } // Update the bridge_detect[v] bridge_detect[v] = min(bridge_detect[u], bridge_detect[v]); // Store the current directed Edge ans.push_back(make_pair(v, u)); } // Condition for Bridges if (bridge_detect[v] == order[v] && l != 0) { flag = 0; } // Return flag return flag; } // Function to print the direction // of edges to make graph SCCs void convert(vector< int > adj[], int n) { // Arrays to store the visited, // bridge_detect and order of // Nodes int order[n] = { 0 }; int bridge_detect[n] = { 0 }; bool mark[n]; // Initialise marks[] as false memset (mark, false , sizeof (mark)); // DFS Traversal from vertex 1 int flag = dfs(adj, order, bridge_detect, mark, 1, 0); // If flag is zero, then Bridge // is present in the graph if (flag == 0) { cout << "-1" ; } // Else print the direction of // Edges assigned else { for ( auto & it : ans) { cout << it.first << "->" << it.second << '\n' ; } } } // Function to create graph void createGraph( int Edges[][2], vector< int > adj[], int M) { // Traverse the Edges for ( int i = 0; i < M; i++) { int u = Edges[i][0]; int v = Edges[i][1]; // Push the edges in an // adjacency list adj[u].push_back(v); adj[v].push_back(u); } } // Driver Code int main() { // N vertices and M Edges int N = 5, M = 6; int Edges[M][2] = { { 0, 1 }, { 0, 2 }, { 1, 2 }, { 1, 4 }, { 2, 3 }, { 3, 4 } }; // To create Adjacency List vector< int > adj[N]; // Create an undirected graph createGraph(Edges, adj, M); // Function Call convert(adj, N); return 0; } |
Java
// Java program for the above approach import java.util.*; import java.lang.*; class GFG{ // To store the assigned Edges static ArrayList< int []> ans; // Flag variable to check Bridges static int flag = 1 ; // Function to implement DFS Traversal static int dfs(ArrayList<ArrayList<Integer>> adj, int [] order, int [] bridge_detect, boolean [] mark, int v, int l) { // Mark the current node as visited mark[v] = true ; // Update the order of node v order[v] = order[l] + 1 ; // Update the bridge_detect for node v bridge_detect[v] = order[v]; // Traverse the adjacency list of // Node v for ( int i = 0 ; i < adj.get(v).size(); i++) { int u = adj.get(v).get(i); // Ignores if same edge is traversed if (u == l) { continue ; } // Ignores the edge u --> v as // v --> u is already processed if (order[v] < order[u]) { continue ; } // Finds a back Edges, cycle present if (mark[u]) { // Update the bridge_detect[v] bridge_detect[v] = Math.min(order[u], bridge_detect[v]); } // Else DFS traversal for current // node in the adjacency list else { dfs(adj, order, bridge_detect, mark, u, v); } // Update the bridge_detect[v] bridge_detect[v] = Math.min(bridge_detect[u], bridge_detect[v]); // Store the current directed Edge ans.add( new int []{v, u}); } // Condition for Bridges if (bridge_detect[v] == order[v] && l != 0 ) { flag = 0 ; } // Return flag return flag; } // Function to print the direction // of edges to make graph SCCs static void convert(ArrayList<ArrayList<Integer>> adj, int n) { // Arrays to store the visited, // bridge_detect and order of // Nodes int [] order = new int [n]; int [] bridge_detect = new int [n]; boolean mark[] = new boolean [n]; // DFS Traversal from vertex 1 int flag = dfs(adj, order, bridge_detect, mark, 1 , 0 ); // If flag is zero, then Bridge // is present in the graph if (flag == 0 ) { System.out.print( "-1" ); } // Else print the direction of // Edges assigned else { for ( int [] it : ans) { System.out.println(it[ 0 ] + "->" + it[ 1 ]); } } } // Function to create graph static void createGraph( int Edges[][], ArrayList<ArrayList<Integer>> adj, int M) { // Traverse the Edges for ( int i = 0 ; i < M; i++) { int u = Edges[i][ 0 ]; int v = Edges[i][ 1 ]; // Push the edges in an // adjacency list adj.get(u).add(v); adj.get(v).add(u); } } // Driver code public static void main(String[] args) { // N vertices and M Edges int N = 5 , M = 6 ; int Edges[][] = { { 0 , 1 }, { 0 , 2 }, { 1 , 2 }, { 1 , 4 }, { 2 , 3 }, { 3 , 4 } }; // To create Adjacency List ArrayList<ArrayList<Integer>> adj = new ArrayList<>(); ans = new ArrayList<>(); for ( int i = 0 ; i < N; i++) adj.add( new ArrayList<>()); // Create an undirected graph createGraph(Edges, adj, M); // Function Call convert(adj, N); } } // This code is contributed by offbeat |
Python3
# Python3 program for # the above approach # To store the assigned # Edges ans = [] # Flag variable to # check Bridges flag = 1 ; # Function to implement # DFS Traversal def dfs(adj, order, bridge_detect, mark, v, l): global flag # Mark the current # node as visited mark[v] = 1 ; # Update the order of # node v order[v] = order[l] + 1 ; # Update the bridge_detect # for node v bridge_detect[v] = order[v]; # Traverse the adjacency list of # Node v for i in range ( len (adj[v])): u = adj[v][i]; # Ignores if same edge # is traversed if (u = = l): continue ; # Ignores the edge u --> v as # v --> u is already processed if (order[v] < order[u]): continue ; # Finds a back Edges, # cycle present if (mark[u]): # Update the bridge_detect[v] bridge_detect[v] = min (order[u], bridge_detect[v]); # Else DFS traversal for current # node in the adjacency list else : dfs(adj, order, bridge_detect, mark, u, v); # Update the bridge_detect[v] bridge_detect[v] = min (bridge_detect[u], bridge_detect[v]); # Store the current # directed Edge ans.append([v, u]); # Condition for Bridges if (bridge_detect[v] = = order[v] and l ! = 0 ): flag = 0 ; # Return flag return flag; # Function to print the # direction of edges to # make graph SCCs def convert(adj, n): # Arrays to store the visited, # bridge_detect and order of # Nodes order = [ 0 for i in range (n)] bridge_detect = [ 0 for i in range (n)] mark = [ False for i in range (n)] # DFS Traversal from # vertex 1 flag = dfs(adj, order, bridge_detect, mark, 1 , 0 ); # If flag is zero, then Bridge # is present in the graph if (flag = = 0 ): print ( - 1 ) # Else print the direction # of Edges assigned else : for it in ans: print ( "{} -> {}" . format (it[ 0 ], it[ 1 ])) # Function to create graph def createGraph(Edges,adj, M): # Traverse the Edges for i in range (M): u = Edges[i][ 0 ]; v = Edges[i][ 1 ]; # Push the edges in an # adjacency list adj[u].append(v); adj[v].append(u); # Driver code if __name__ = = "__main__" : # N vertices and M Edges N = 5 M = 6 ; Edges = [[ 0 , 1 ], [ 0 , 2 ], [ 1 , 2 ], [ 1 , 4 ], [ 2 , 3 ], [ 3 , 4 ]]; # To create Adjacency List adj = [[] for i in range (N)] # Create an undirected graph createGraph(Edges, adj, M); # Function Call convert(adj, N); # This code is contributed by rutvik_56 |
C#
// C# program for the above approach using System; using System.Collections; using System.Collections.Generic; class GFG{ // To store the assigned Edges static ArrayList ans; // Flag variable to check Bridges static int flag = 1; // Function to implement DFS Traversal static int dfs(ArrayList adj, int [] order, int [] bridge_detect, bool [] mark, int v, int l) { // Mark the current node as visited mark[v] = true ; // Update the order of node v order[v] = order[l] + 1; // Update the bridge_detect for node v bridge_detect[v] = order[v]; // Traverse the adjacency list of // Node v for ( int i = 0; i < ((ArrayList)adj[v]).Count; i++) { int u = ( int )((ArrayList)adj[v])[i]; // Ignores if same edge is traversed if (u == l) { continue ; } // Ignores the edge u --> v as // v --> u is already processed if (order[v] < order[u]) { continue ; } // Finds a back Edges, cycle present if (mark[u]) { // Update the bridge_detect[v] bridge_detect[v] = Math.Min(order[u], bridge_detect[v]); } // Else DFS traversal for current // node in the adjacency list else { dfs(adj, order, bridge_detect, mark, u, v); } // Update the bridge_detect[v] bridge_detect[v] = Math.Min(bridge_detect[u], bridge_detect[v]); // Store the current directed Edge ans.Add( new int []{v, u}); } // Condition for Bridges if (bridge_detect[v] == order[v] && l != 0) { flag = 0; } // Return flag return flag; } // Function to print the direction // of edges to make graph SCCs static void convert(ArrayList adj, int n) { // Arrays to store the visited, // bridge_detect and order of // Nodes int [] order = new int [n]; int [] bridge_detect = new int [n]; bool []mark = new bool [n]; // DFS Traversal from vertex 1 int flag = dfs(adj, order, bridge_detect, mark, 1, 0); // If flag is zero, then Bridge // is present in the graph if (flag == 0) { Console.Write( "-1" ); } // Else print the direction of // Edges assigned else { foreach ( int [] it in ans) { Console.WriteLine(it[0] + "->" + it[1]); } } } // Function to create graph static void createGraph( int [,]Edges, ArrayList adj, int M) { // Traverse the Edges for ( int i = 0; i < M; i++) { int u = Edges[i, 0]; int v = Edges[i, 1]; // Push the edges in an // adjacency list ((ArrayList)adj[u]).Add(v); ((ArrayList)adj[v]).Add(u); } } // Driver code public static void Main( string [] args) { // N vertices and M Edges int N = 5, M = 6; int [,]Edges = { { 0, 1 }, { 0, 2 }, { 1, 2 }, { 1, 4 }, { 2, 3 }, { 3, 4 } }; // To create Adjacency List ArrayList adj = new ArrayList(); ans = new ArrayList(); for ( int i = 0; i < N; i++) adj.Add( new ArrayList()); // Create an undirected graph createGraph(Edges, adj, M); // Function Call convert(adj, N); } } // This code is contributed by pratham76 |
Javascript
<script> // Javascript program for the above approach // To store the assigned Edges let ans; // Flag variable to check Bridges let flag = 1; // Function to implement DFS Traversal function dfs(adj, order, bridge_detect, mark, v, l) { // Mark the current node as visited mark[v] = true ; // Update the order of node v order[v] = order[l] + 1; // Update the bridge_detect for node v bridge_detect[v] = order[v]; // Traverse the adjacency list of // Node v for (let i = 0; i < adj[v].length; i++) { let u = adj[v][i]; // Ignores if same edge is traversed if (u == l) { continue ; } // Ignores the edge u --> v as // v --> u is already processed if (order[v] < order[u]) { continue ; } // Finds a back Edges, cycle present if (mark[u]) { // Update the bridge_detect[v] bridge_detect[v] = Math.min(order[u], bridge_detect[v]); } // Else DFS traversal for current // node in the adjacency list else { dfs(adj, order, bridge_detect, mark, u, v); } // Update the bridge_detect[v] bridge_detect[v] = Math.min(bridge_detect[u], bridge_detect[v]); // Store the current directed Edge ans.push([v, u]); } // Condition for Bridges if (bridge_detect[v] == order[v] && l != 0) { flag = 0; } // Return flag return flag; } // Function to print the direction // of edges to make graph SCCs function convert(adj, n) { // Arrays to store the visited, // bridge_detect and order of // Nodes let order = new Array(n); let bridge_detect = new Array(n); let mark = new Array(n); // DFS Traversal from vertex 1 let flag = dfs(adj, order, bridge_detect, mark, 1, 0); // If flag is zero, then Bridge // is present in the graph if (flag == 0) { document.write( "-1" ); } // Else print the direction of // Edges assigned else { for (let it = 0; it < ans.length - 1; it++) { document.write(ans[it][0] + "->" + ans[it][1] + "</br>" ); } } } // Function to create graph function createGraph(Edges, adj, M) { // Traverse the Edges for (let i = 0; i < M; i++) { let u = Edges[i][0]; let v = Edges[i][1]; // Push the edges in an // adjacency list adj[u].push(v); adj[v].push(u); } } // N vertices and M Edges let N = 5, M = 6; let Edges = [ [ 0, 1 ], [ 0, 2 ], [ 1, 2 ], [ 1, 4 ], [ 2, 3 ], [ 3, 4 ] ]; // To create Adjacency List let adj = []; ans = []; for (let i = 0; i < N; i++) adj.push([]); // Create an undirected graph createGraph(Edges, adj, M); // Function Call convert(adj, N); // This code is contributed by suresh07. </script> |
0->1 2->0 4->1 3->4 2->3 1->2
Time Complexity: O(N)
Auxiliary Space: O(N)
Please Login to comment...