Open In App

Check if a given Graph is 2-edge connected or not

Last Updated : 27 Feb, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

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


Output

Given graph is not 2-edge connected

Time Complexity: O(V + E) 
Auxiliary Space: O(V)



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads