Check if a given Graph is 2-edge connected or not
Given an undirected graph G, with V vertices and E edges, the task is to check whether the graph is 2-edge connected or not. A graph is said to be 2-edge connected if, on removing any edge of the graph, it still remains connected, i.e. it contains no Bridges.
Examples:
Input: V = 7, E = 9
Output: Yes
Explanation:
Given any vertex in the graph, we can reach any other vertex in the graph. Moreover, removing any edge from the graph does not affect its connectivity. So, the graph is said to be 2-edge connected.Input: V = 8, E = 9
example2
Output: No
Explanation:
On removal of the edge between vertex 3 and vertex 4, the graph is not connected anymore. So, the graph is not 2-edge connected.
Naive Approach: The Naive approach is to check that on removing any edge X, if the remaining graph G – X is connected or not. If the graph remains connected on removing every edge one by one then it is a 2-edge connected graph. To implement the above idea, remove an edge and perform Depth First Search(DFS) or Breadth-First Search(BFS) from any vertex and check if all vertices are covered or not. Repeat this process for all E edges. If all vertices cannot be traversed for any edge, print No. Otherwise, print Yes.
Time Complexity: O(E * ( V + E))
Auxiliary Space: O(1)
Efficient Approach: The idea to solve this problem is:
Bridges in a graph: An edge in an undirected connected graph is a bridge if removing it disconnects the graph. For a disconnected undirected graph, definition is similar, a bridge is an edge removing which increases number of disconnected components.
=> If there is any bridge in the graph then it will never be a 2-edge connected otherwise it will be a 2-edge connected.
Below is the Implementation of the above approach:
C++
// A C++ program to find bridges in a given undirected graph #include <bits/stdc++.h> #include <list> #define NIL -1 using namespace std; // A class that represents an undirected graph class Graph { int V; // No. of vertices list< int >* adj; // A dynamic array of adjacency lists void bridgeUtil( int v, bool visited[], int disc[], int low[], int parent[]); public : int count = 0; Graph( int V); // Constructor void addEdge( int v, int w); // to add an edge to graph void bridge(); // prints all bridges }; Graph::Graph( int V) { this ->V = V; adj = new list< int >[V]; } void Graph::addEdge( int v, int w) { adj[v].push_back(w); adj[w].push_back(v); // Note: the graph is undirected } // A recursive function that finds and prints bridges using // DFS traversal // u --> The vertex to be visited next // visited[] --> keeps track of visited vertices // disc[] --> Stores discovery times of visited vertices // parent[] --> Stores parent vertices in DFS tree void Graph::bridgeUtil( int u, bool visited[], int disc[], int low[], int parent[]) { // A static variable is used for simplicity, we can // avoid use of static variable by passing a pointer. static int time = 0; // Mark the current node as visited visited[u] = true ; // Initialize discovery time and low value disc[u] = low[u] = ++ time ; // Go through all vertices adjacent to this list< int >::iterator i; for (i = adj[u].begin(); i != adj[u].end(); ++i) { int v = *i; // v is current adjacent of u // If v is not visited yet, then recur for it if (!visited[v]) { parent[v] = u; bridgeUtil(v, visited, disc, low, parent); // Check if the subtree rooted with v has a // connection to one of the ancestors of u low[u] = min(low[u], low[v]); // If the lowest vertex reachable from subtree // under v is below u in DFS tree, then u-v // is a bridge if (low[v] > disc[u]) count++; } // Update low value of u for parent function calls. else if (v != parent[u]) low[u] = min(low[u], disc[v]); } } // DFS based function to find all bridges. It uses recursive // function bridgeUtil() void Graph::bridge() { // Mark all the vertices as not visited bool * visited = new bool [V]; int * disc = new int [V]; int * low = new int [V]; int * parent = new int [V]; // Initialize parent and visited arrays for ( int i = 0; i < V; i++) { parent[i] = NIL; visited[i] = false ; } // Call the recursive helper function to find Bridges // in DFS tree rooted with vertex 'i' for ( int i = 0; i < V; i++) if (visited[i] == false ) bridgeUtil(i, visited, disc, low, parent); } // Driver Code int main() { Graph g1(6); g1.addEdge(0, 1); g1.addEdge(1, 2); g1.addEdge(2, 0); g1.addEdge(1, 3); g1.addEdge(3, 4); g1.addEdge(4, 5); g1.addEdge(5, 3); g1.bridge(); if (g1.count == 0) { cout << "Given graph is 2-edge connected" ; } else { cout << "Given graph is not 2-edge connected" ; } return 0; } |
Java
// A Java program to find bridges in a given undirected // graph import java.io.*; import java.util.*; import java.util.LinkedList; // This class represents a undirected graph using adjacency // list representation class Graph { private int V; // No. of vertices // Array of lists for Adjacency List Representation private LinkedList<Integer> adj[]; int time = 0 ; static final int NIL = - 1 ; static int count = 0 ; // Constructor @SuppressWarnings ( "unchecked" ) Graph( int v) { V = v; adj = new LinkedList[v]; for ( int i = 0 ; i < v; ++i) adj[i] = new LinkedList(); } // Function to add an edge into the graph void addEdge( int v, int w) { adj[v].add(w); // Add w to v's list. adj[w].add(v); // Add v to w's list } // A recursive function that finds and prints bridges // using DFS traversal // u --> The vertex to be visited next // visited[] --> keeps track of visited vertices // disc[] --> Stores discovery times of visited vertices // parent[] --> Stores parent vertices in DFS tree void bridgeUtil( int u, boolean visited[], int disc[], int low[], int parent[]) { // Mark the current node as visited visited[u] = true ; // Initialize discovery time and low value disc[u] = low[u] = ++time; // Go through all vertices adjacent to this Iterator<Integer> i = adj[u].iterator(); while (i.hasNext()) { int v = i.next(); // v is current adjacent of u // If v is not visited yet, then make it a child // of u in DFS tree and recur for it. // If v is not visited yet, then recur for it if (!visited[v]) { parent[v] = u; bridgeUtil(v, visited, disc, low, parent); // Check if the subtree rooted with v has a // connection to one of the ancestors of u low[u] = Math.min(low[u], low[v]); // If the lowest vertex reachable from // subtree under v is below u in DFS tree, // then u-v is a bridge if (low[v] > disc[u]) count++; } // Update low value of u for parent function // calls. else if (v != parent[u]) low[u] = Math.min(low[u], disc[v]); } } // DFS based function to find all bridges. It uses // recursive function bridgeUtil() void bridge() { // Mark all the vertices as not visited boolean visited[] = new boolean [V]; int disc[] = new int [V]; int low[] = new int [V]; int parent[] = new int [V]; // Initialize parent and visited, and // ap(articulation point) arrays for ( int i = 0 ; i < V; i++) { parent[i] = NIL; visited[i] = false ; } // Call the recursive helper function to find // Bridges in DFS tree rooted with vertex 'i' for ( int i = 0 ; i < V; i++) if (visited[i] == false ) bridgeUtil(i, visited, disc, low, parent); } public static void main(String args[]) { // Create graphs given in above diagrams System.out.println( "Bridges in first graph " ); Graph g1 = new Graph( 6 ); g1.addEdge( 0 , 1 ); g1.addEdge( 1 , 2 ); g1.addEdge( 2 , 0 ); g1.addEdge( 1 , 3 ); g1.addEdge( 3 , 4 ); g1.addEdge( 4 , 5 ); g1.addEdge( 5 , 3 ); g1.bridge(); if (g1.count == 0 ) { System.out.println( "Given graph is 2-edge connected:" ); } else { System.out.println( "Given graph is not 2-edge connected:" ); } } } // This code is contributed by Aakash Hasija |
Python3
# Python program to find bridges in a given undirected graph # Complexity : O(V+E) from collections import defaultdict # This class represents an undirected graph using adjacency list representation class Graph: count = 0 def __init__( self , vertices): self .V = vertices # No. of vertices self .graph = defaultdict( list ) # default dictionary to store graph self .Time = 0 # function to add an edge to graph def addEdge( self , u, v): self .graph[u].append(v) self .graph[v].append(u) '''A recursive function that finds and prints bridges using DFS traversal u --> The vertex to be visited next visited[] --> keeps track of visited vertices disc[] --> Stores discovery times of visited vertices parent[] --> Stores parent vertices in DFS tree''' def bridgeUtil( self , u, visited, parent, low, disc): # Mark the current node as visited and print it visited[u] = True # Mark the current node as visited and print it disc[u] = self .Time low[u] = self .Time self .Time + = 1 # count = 0 # Recur for all the vertices adjacent to this vertex for v in self .graph[u]: # If v is not visited yet, then make it a child of u # in DFS tree and recur for it if visited[v] = = False : parent[v] = u self .bridgeUtil(v, visited, parent, low, disc) # Check if the subtree rooted with v has a connection to # one of the ancestors of u low[u] = min (low[u], low[v]) ''' If the lowest vertex reachable from subtree under v is below u in DFS tree, then u-v is a bridge''' if low[v] > disc[u]: self .count + = 1 # Update low value of u for parent function calls. elif v ! = parent[u]: low[u] = min (low[u], disc[v]) # DFS based function to find all bridges. It uses recursive # function bridgeUtil() def bridge( self ): # Mark all the vertices as not visited and Initialize parent and visited, # and ap(articulation point) arrays visited = [ False ] * ( self .V) disc = [ float ( "Inf" )] * ( self .V) low = [ float ( "Inf" )] * ( self .V) parent = [ - 1 ] * ( self .V) # Call the recursive helper function to find bridges # in DFS tree rooted with vertex 'i' for i in range ( self .V): if visited[i] = = False : self .bridgeUtil(i, visited, parent, low, disc) # Create a graph given in the above diagram g1 = Graph( 6 ) g1.addEdge( 0 , 1 ) g1.addEdge( 1 , 2 ) g1.addEdge( 2 , 0 ) g1.addEdge( 1 , 3 ) g1.addEdge( 3 , 4 ) g1.addEdge( 4 , 5 ) g1.addEdge( 5 , 3 ) g1.bridge() if g1.count = = 0 : print ( "Given graph is 2-edge connected" ) else : print ( "Given graph is not 2-edge connected" ) # This code is contributed by Neelam Yadav |
C#
using System; using System.Collections.Generic; //This class represents an undirected graph using adjacency list representation class Graph { static int count; int V; int Time; Dictionary< int , List< int >> graph; public Graph( int vertices) { V = vertices; //No. of vertices graph = new Dictionary< int , List< int >>(); Time = 0; } //function to add an edge to graph public void AddEdge( int u, int v) { if (!graph.ContainsKey(u)) graph[u] = new List< int >(); if (!graph.ContainsKey(v)) graph[v] = new List< int >(); graph[u].Add(v); graph[v].Add(u); } void BridgeUtil( int u, bool [] visited, int [] parent, int [] low, int [] disc) { //Mark the current node as visited and print it visited[u] = true ; //Mark the current node as visited and print it disc[u] = Time; low[u] = Time; Time++; //count = 0 //Recur for all the vertices adjacent to this vertex foreach ( int v in graph[u]) { // If v is not visited yet, then make it a child of u //in DFS tree and recur for it if (!visited[v]) { parent[v] = u; BridgeUtil(v, visited, parent, low, disc); //Check if the subtree rooted with v has a connection to //one of the ancestors of u low[u] = Math.Min(low[u], low[v]); if (low[v] > disc[u]) count++; } //Update low value of u for parent function calls. else if (v != parent[u]) low[u] = Math.Min(low[u], disc[v]); } } // DFS based function to find all bridges. It uses recursive // function bridgeUtil() public void Bridge() { bool [] visited = new bool [V]; int [] disc = new int [V]; int [] low = new int [V]; int [] parent = new int [V]; for ( int i = 0; i < V; i++) { if (!visited[i]) { BridgeUtil(i, visited, parent, low, disc); } } } public static int GetBridgeCount() { return count; } } class Program { //Driver code static void Main( string [] args) { Graph g1 = new Graph(6); g1.AddEdge(0, 1); g1.AddEdge(1, 2); g1.AddEdge(2, 0); g1.AddEdge(1, 3); g1.AddEdge(3, 4); g1.AddEdge(4, 5); g1.AddEdge(5, 3); g1.Bridge(); int count = Graph.GetBridgeCount(); if (count == 0) Console.WriteLine( "Given graph is 2-edge connected" ); else Console.WriteLine( "Given graph is not 2-edge connected" ); Console.ReadKey(); } } |
Javascript
// A JavaScript program to find bridges in a given undirected graph // Create a class for Graph class Graph { // Initialize the constructor with number of vertices constructor(v) { this .V = v; this .adj = Array(v).fill().map(() => []); this .time = 0; this .NIL = -1; this .count = 0; } // Function to add an edge into the graph addEdge(v, w) { this .adj[v].push(w); this .adj[w].push(v); } // A recursive function that finds and prints bridges // using DFS traversal // u --> The vertex to be visited next // visited[] --> keeps track of visited vertices // disc[] --> Stores discovery times of visited vertices // parent[] --> Stores parent vertices in DFS tree bridgeUtil(u, visited, disc, low, parent) { visited[u] = true ; disc[u] = low[u] = ++ this .time; for (let v of this .adj[u]) { if (!visited[v]) { parent[v] = u; this .bridgeUtil(v, visited, disc, low, parent); low[u] = Math.min(low[u], low[v]); if (low[v] > disc[u]) this .count++; } else if (v != parent[u]) low[u] = Math.min(low[u], disc[v]); } } // DFS based function to find all bridges. It uses // recursive function bridgeUtil() bridge() { let visited = Array( this .V).fill( false ); let disc = Array( this .V).fill(0); let low = Array( this .V).fill(0); let parent = Array( this .V).fill( this .NIL); for (let i = 0; i < this .V; i++) { if (visited[i] === false ) { this .bridgeUtil(i, visited, disc, low, parent); } } } } // Create graphs given in above diagrams let g1 = new Graph(6); g1.addEdge(0, 1); g1.addEdge(1, 2); g1.addEdge(2, 0); g1.addEdge(1, 3); g1.addEdge(3, 4); g1.addEdge(4, 5); g1.addEdge(5, 3); g1.bridge(); if (g1.count == 0) { console.log( "Given graph is 2-edge connected" ); } else { console.log( "Given graph is not 2-edge connected" ); } // This code is contributed by sankar |
Given graph is not 2-edge connected
Time Complexity: O(V + E)
Auxiliary Space: O(V)
Please Login to comment...