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
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:
// 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;
} |
// 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 |
# 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 |
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();
}
} |
// 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)