Given an undirected graph, the task is to count the maximum number of Bridges between any two vertices of the given graph.
Examples:
Input: Graph 1 ------- 2 ------- 3 -------- 4 | | | | 5 ------- 6 Output: 2 Explanation: There are 2 bridges, (1 - 2) and (3 - 4), in the path from 1 to 4. Input: Graph: 1 ------- 2 ------- 3 ------- 4 Output: 3 Explanation: There are 3 bridges, (1 - 2), (2 - 3) and (3 - 4) in the path from 1 to 4.
Approach:
Follow the steps below to solve the problem:
- Find all the bridges in the graph and store them in a vector.
- Removal of all the bridges reduces the graph to small components.
- These small components do not have any bridges, and they are weakly connected components that do not contain bridges in them.
- Generate a tree consisting of the nodes connected by bridges, with the bridges as the edges.
- Now, the maximum bridges in a path between any node are equal to the diameter of this tree.
- Hence, find the diameter of this tree and print it as the answer.
Below is the implementation of the above approach
C++
// C++ program to find the // maximum number of bridges // in any path of the given graph #include <bits/stdc++.h> using namespace std;
const int N = 1e5 + 5;
// Stores the nodes // and their connections vector<vector< int > > v(N);
// Store the tree with // Bridges as the edges vector<vector< int > > g(N);
// Stores the visited nodes vector< bool > vis(N, 0);
// for finding bridges vector< int > in(N), low(N);
// for Disjoint Set Union vector< int > parent(N), rnk(N);
// for storing actual bridges vector<pair< int , int > > bridges;
// Stores the number of // nodes and edges int n, m;
// For finding bridges int timer = 0;
int find_set( int a)
{ // Function to find root of
// the component in which
// A lies
if (parent[a] == a)
return a;
// Doing path compression
return parent[a]
= find_set(parent[a]);
} void union_set( int a, int b)
{ // Function to do union
// between a and b
int x = find_set(a), y = find_set(b);
// If both are already in the
// same component
if (x == y)
return ;
// If both have same rank,
// then increase anyone's rank
if (rnk[x] == rnk[y])
rnk[x]++;
if (rnk[y] > rnk[x])
swap(x, y);
parent[y] = x;
} // Function to find bridges void dfsBridges( int a, int par)
{ vis[a] = 1;
// Initialize in time and
// low value
in[a] = low[a] = timer++;
for ( int i v[a]) {
if (i == par)
continue ;
if (vis[i])
// Update the low value
// of the parent
low[a] = min(low[a], in[i]);
else {
// Perform DFS on its child
// updating low if the child
// has connection with any
// ancestor
dfsBridges(i, a);
low[a] = min(low[a], low[i]);
if (in[a] < low[i])
// Bridge found
bridges.push_back(make_pair(i, a));
// Otherwise
else
// Find union between parent
// and child as they
// are in same component
union_set(i, a);
}
}
} // Function to find diameter of the // tree for storing max two depth child int dfsDiameter( int a, int par, int & diameter)
{ int x = 0, y = 0;
for ( int i g[a]) {
if (i == par)
continue ;
int mx = dfsDiameter(i, a, diameter);
// Finding max two depth
// from its children
if (mx > x) {
y = x;
x = mx;
}
else if (mx > y)
y = mx;
}
// Update diameter with the
// sum of max two depths
diameter = max(diameter, x + y);
// Return the maximum depth
return x + 1;
} // Function to find maximum // bridges between // any two nodes int findMaxBridges()
{ for ( int i = 0; i <= n; i++) {
parent[i] = i;
rnk[i] = 1;
}
// DFS to find bridges
dfsBridges(1, 0);
// If no bridges are found
if (bridges.empty())
return 0;
int head = -1;
// Iterate over all bridges
for ( auto & i bridges) {
// Find the endpoints
int a = find_set(i.first);
int b = find_set(i.second);
// Generate the tree with
// bridges as the edges
g[a].push_back(b);
g[b].push_back(a);
// Update the head
head = a;
}
int diameter = 0;
dfsDiameter(head, 0, diameter);
// Return the diameter
return diameter;
} // Driver Code int main()
{ /*
Graph =>
1 ---- 2 ---- 3 ---- 4
| |
5 ---- 6
*/
n = 6, m = 6;
v[1].push_back(2);
v[2].push_back(1);
v[2].push_back(3);
v[3].push_back(2);
v[2].push_back(5);
v[5].push_back(2);
v[5].push_back(6);
v[6].push_back(5);
v[6].push_back(3);
v[3].push_back(6);
v[3].push_back(4);
v[4].push_back(4);
int ans = findMaxBridges();
cout << ans << endl;
return 0;
} |
Java
// Java program to find the // maximum number of bridges // in any path of the given graph import java.util.*;
class GFG{
static int N = ( int )1e5 + 5 ;
// Stores the nodes // and their connections static Vector<Integer> []v =
new Vector[N];
// Store the tree with // Bridges as the edges static Vector<Integer> []g =
new Vector[N];
// Stores the visited nodes static boolean []vis =
new boolean [N];
// For finding bridges static int []in = new int [N];
static int []low = new int [N];
// for Disjoint Set Union static int []parent = new int [N];
static int []rnk = new int [N];
// For storing actual bridges static Vector<pair> bridges =
new Vector<>();
// Stores the number of // nodes and edges static int n, m;
// For finding bridges static int timer = 0 ;
static int diameter;
static class pair
{ int first, second;
public pair( int first,
int second)
{
this .first = first;
this .second = second;
}
} static void swap( int x,
int y)
{ int temp = x;
x = y;
y = temp;
} static int find_set( int a)
{ // Function to find root of
// the component in which
// A lies
if (parent[a] == a)
return a;
// Doing path compression
return parent[a] =
find_set(parent[a]);
} static void union_set( int a, int b)
{ // Function to do union
// between a and b
int x = find_set(a),
y = find_set(b);
// If both are already
// in the same component
if (x == y)
return ;
// If both have same rank,
// then increase anyone's rank
if (rnk[x] == rnk[y])
rnk[x]++;
if (rnk[y] > rnk[x])
swap(x, y);
parent[y] = x;
} // Function to find bridges static void dfsBridges( int a,
int par)
{ vis[a] = true ;
// Initialize in time and
// low value
in[a] = low[a] = timer++;
for ( int i : v[a])
{
if (i == par)
continue ;
if (vis[i])
// Update the low value
// of the parent
low[a] = Math.min(low[a],
in[i]);
else
{
// Perform DFS on its child
// updating low if the child
// has connection with any
// ancestor
dfsBridges(i, a);
low[a] = Math.min(low[a],
low[i]);
if (in[a] < low[i])
// Bridge found
bridges.add( new pair(i, a));
// Otherwise
else
// Find union between parent
// and child as they
// are in same component
union_set(i, a);
}
}
} // Function to find diameter // of the tree for storing // max two depth child static int dfsDiameter( int a,
int par)
{ int x = 0 , y = 0 ;
for ( int i : g[a])
{
if (i == par)
continue ;
int mx = dfsDiameter(i, a);
// Finding max two depth
// from its children
if (mx > x)
{
y = x;
x = mx;
}
else if (mx > y)
y = mx;
}
// Update diameter with the
// sum of max two depths
diameter = Math.max(diameter,
x + y);
// Return the maximum depth
return x + 1 ;
} // Function to find maximum // bridges between // any two nodes static int findMaxBridges()
{ for ( int i = 0 ; i <= n; i++)
{
parent[i] = i;
rnk[i] = 1 ;
}
// DFS to find bridges
dfsBridges( 1 , 0 );
// If no bridges are found
if (bridges.isEmpty())
return 0 ;
int head = - 1 ;
// Iterate over all bridges
for (pair i : bridges)
{
// Find the endpoints
int a = find_set(i.first);
int b = find_set(i.second);
// Generate the tree with
// bridges as the edges
g[a].add(b);
g[b].add(a);
// Update the head
head = a;
}
diameter = 0 ;
dfsDiameter(head, 0 );
// Return the diameter
return diameter;
} // Driver Code public static void main(String[] args)
{ /*
Graph =>
1 ---- 2 ---- 3 ---- 4
| |
5 ---- 6
*/
n = 6 ;
m = 6 ;
for ( int i = 0 ; i < v.length; i++)
v[i] = new Vector<Integer>();
for ( int i = 0 ; i < g.length; i++)
g[i] = new Vector<Integer>();
v[ 1 ].add( 2 );
v[ 2 ].add( 1 );
v[ 2 ].add( 3 );
v[ 3 ].add( 2 );
v[ 2 ].add( 5 );
v[ 5 ].add( 2 );
v[ 5 ].add( 6 );
v[ 6 ].add( 5 );
v[ 6 ].add( 3 );
v[ 3 ].add( 6 );
v[ 3 ].add( 4 );
v[ 4 ].add( 4 );
int ans = findMaxBridges();
System.out.print(ans + "\n" );
} } // This code is contributed by Princi Singh |
Python3
# Python3 program to find the # maximum number of bridges # in any path of the given graph N = 100005
# Stores the nodes # and their connections v = []
# Store the tree with # Bridges as the edges g = []
# Stores the visited nodes vis = [ False ] * (N)
# For finding bridges In = [ 0 ] * (N)
low = [ 0 ] * (N)
# for Disjoint Set Union parent = [ 0 ] * (N)
rnk = [ 0 ] * (N)
# For storing actual bridges bridges = []
# Stores the number of # nodes and edges n, m = 6 , 6
# For finding bridges timer = 0
diameter = 0
def swap(x, y):
temp = x
x = y
y = temp
def find_set(a):
global N, v, g, vis, In, low, parent, rnk, bridges, n, m, timer, diameter
# Function to find root of
# the component in which
# A lies
if parent[a] = = a:
return a
# Doing path compression
parent[a] = find_set(parent[a])
return parent[a]
def union_set(a, b):
global N, v, g, vis, In, low, parent, rnk, bridges, n, m, timer, diameter
# Function to do union
# between a and b
x, y = find_set(a), find_set(b)
# If both are already
# in the same component
if x = = y:
return
# If both have same rank,
# then increase anyone's rank
if rnk[x] = = rnk[y]:
rnk[x] + = 1
if rnk[y] > rnk[x]:
swap(x, y)
parent[y] = x
# Function to find bridges def dfsBridges(a, par):
global N, v, g, vis, In, low, parent, rnk, bridges, n, m, timer, diameter
vis[a] = True
# Initialize in time and
# low value
timer + = 1
In[a], low[a] = timer, timer
for i in range ( len (v[a])):
if v[a][i] = = par:
continue
if vis[v[a][i]]:
# Update the low value
# of the parent
low[a] = min (low[a], In[v[a][i]])
else :
# Perform DFS on its child
# updating low if the child
# has connection with any
# ancestor
dfsBridges(v[a][i], a)
low[a] = min (low[a], low[v[a][i]])
if In[a] < low[v[a][i]]:
# Bridge found
bridges.append([v[a][i], a])
# Otherwise
else :
# Find union between parent
# and child as they
# are in same component
union_set(v[a][i], a)
# Function to find diameter # of the tree for storing # max two depth child def dfsDiameter(a, par):
global N, v, g, vis, In, low, parent, rnk, bridges, n, m, timer, diameter
x, y = 0 , 0
for i in range ( len (g[a])):
if g[a][i] = = par:
continue
mx = dfsDiameter(g[a][i], a)
# Finding max two depth
# from its children
if mx > x:
y = x
x = mx
elif mx > y:
y = mx
# Update diameter with the
# sum of max two depths
diameter = max (diameter, x + y)
# Return the maximum depth
return x + 1
# Function to find maximum # bridges between # any two nodes def findMaxBridges():
global N, v, g, vis, In, low, parent, rnk, bridges, n, m, timer, diameter
for i in range (n + 1 ):
parent[i] = i
rnk[i] = 1
# DFS to find bridges
dfsBridges( 1 , 0 );
# If no bridges are found
if len (bridges) = = 0 :
return 0
head = - 1
# Iterate over all bridges
for i in range ( len (bridges)):
# Find the endpoints
a = find_set(bridges[i][ 0 ])
b = find_set(bridges[i][ 1 ])
# Generate the tree with
# bridges as the edges
g[a].append(b)
g[b].append(a)
# Update the head
head = a
diameter = 0
dfsDiameter(head, 0 )
# Return the diameter
return diameter
""" Graph =>
1 ---- 2 ---- 3 ---- 4
| |
5 ---- 6
""" for i in range (N):
v.append([])
for i in range (N):
g.append([])
v[ 1 ].append( 2 )
v[ 2 ].append( 1 )
v[ 2 ].append( 3 )
v[ 3 ].append( 2 )
v[ 2 ].append( 5 )
v[ 5 ].append( 2 )
v[ 5 ].append( 6 )
v[ 6 ].append( 5 )
v[ 6 ].append( 3 )
v[ 3 ].append( 6 )
v[ 3 ].append( 4 )
v[ 4 ].append( 4 )
ans = findMaxBridges()
print (ans)
# This code is contributed by suresh07. |
C#
// C# program to find the // maximum number of bridges // in any path of the given graph using System;
using System.Collections.Generic;
class GFG{
static int N = ( int )1e5 + 5;
// Stores the nodes // and their connections static List< int > []v =
new List< int >[N];
// Store the tree with // Bridges as the edges static List< int > []g =
new List< int >[N];
// Stores the visited nodes static bool []vis =
new bool [N];
// For finding bridges static int []init = new int [N];
static int []low = new int [N];
// for Disjoint Set Union static int []parent = new int [N];
static int []rnk = new int [N];
// For storing actual bridges static List<pair> bridges =
new List<pair>();
// Stores the number of // nodes and edges static int n, m;
// For finding bridges static int timer = 0;
static int diameter;
class pair
{ public int first, second;
public pair( int first,
int second)
{
this .first = first;
this .second = second;
}
} static void swap( int x,
int y)
{ int temp = x;
x = y;
y = temp;
} static int find_set( int a)
{ // Function to find root of
// the component in which
// A lies
if (parent[a] == a)
return a;
// Doing path compression
return parent[a] =
find_set(parent[a]);
} static void union_set( int a,
int b)
{ // Function to do union
// between a and b
int x = find_set(a),
y = find_set(b);
// If both are already
// in the same component
if (x == y)
return ;
// If both have same rank,
// then increase anyone's rank
if (rnk[x] == rnk[y])
rnk[x]++;
if (rnk[y] > rnk[x])
swap(x, y);
parent[y] = x;
} // Function to find bridges static void dfsBridges( int a,
int par)
{ vis[a] = true ;
// Initialize in time and
// low value
init[a] = low[a] = timer++;
foreach ( int i in v[a])
{
if (i == par)
continue ;
if (vis[i])
// Update the low value
// of the parent
low[a] = Math.Min(low[a],
init[i]);
else
{
// Perform DFS on its child
// updating low if the child
// has connection with any
// ancestor
dfsBridges(i, a);
low[a] = Math.Min(low[a],
low[i]);
if (init[a] < low[i])
// Bridge found
bridges.Add( new pair(i, a));
// Otherwise
else
// Find union between parent
// and child as they
// are in same component
union_set(i, a);
}
}
} // Function to find diameter // of the tree for storing // max two depth child static int dfsDiameter( int a,
int par)
{ int x = 0, y = 0;
foreach ( int i in g[a])
{
if (i == par)
continue ;
int mx = dfsDiameter(i, a);
// Finding max two depth
// from its children
if (mx > x)
{
y = x;
x = mx;
}
else if (mx > y)
y = mx;
}
// Update diameter with the
// sum of max two depths
diameter = Math.Max(diameter,
x + y);
// Return the
// maximum depth
return x + 1;
} // Function to find maximum // bridges between // any two nodes static int findMaxBridges()
{ for ( int i = 0; i <= n; i++)
{
parent[i] = i;
rnk[i] = 1;
}
// DFS to find bridges
dfsBridges(1, 0);
// If no bridges are found
if (bridges.Count == 0)
return 0;
int head = -1;
// Iterate over all bridges
foreach (pair i in bridges)
{
// Find the endpoints
int a = find_set(i.first);
int b = find_set(i.second);
// Generate the tree with
// bridges as the edges
g[a].Add(b);
g[b].Add(a);
// Update the head
head = a;
}
diameter = 0;
dfsDiameter(head, 0);
// Return the diameter
return diameter;
} // Driver Code public static void Main(String[] args)
{ /*
Graph =>
1 ---- 2 ---- 3 ---- 4
| |
5 ---- 6
*/
n = 6;
m = 6;
for ( int i = 0; i < v.Length; i++)
v[i] = new List< int >();
for ( int i = 0; i < g.Length; i++)
g[i] = new List< int >();
v[1].Add(2);
v[2].Add(1);
v[2].Add(3);
v[3].Add(2);
v[2].Add(5);
v[5].Add(2);
v[5].Add(6);
v[6].Add(5);
v[6].Add(3);
v[3].Add(6);
v[3].Add(4);
v[4].Add(4);
int ans = findMaxBridges();
Console.Write(ans + "\n" );
} } // This code is contributed by Amit Katiyar |
Javascript
<script> // Javascript program to find the
// maximum number of bridges
// in any path of the given graph
let N = 1e5 + 5;
// Stores the nodes
// and their connections
let v = new Array(N);
// Store the tree with
// Bridges as the edges
let g = new Array(N);
// Stores the visited nodes
let vis = new Array(N);
// For finding bridges
let In = new Array(N);
let low = new Array(N);
// for Disjoint Set Union
let parent = new Array(N);
let rnk = new Array(N);
// For storing actual bridges
let bridges = [];
// Stores the number of
// nodes and edges
let n, m;
// For finding bridges
let timer = 0;
let diameter;
function swap(x, y)
{
let temp = x;
x = y;
y = temp;
}
function find_set(a)
{
// Function to find root of
// the component in which
// A lies
if (parent[a] == a)
return a;
// Doing path compression
return parent[a] = find_set(parent[a]);
}
function union_set(a, b)
{
// Function to do union
// between a and b
let x = find_set(a), y = find_set(b);
// If both are already
// in the same component
if (x == y)
return ;
// If both have same rank,
// then increase anyone's rank
if (rnk[x] == rnk[y])
rnk[x]++;
if (rnk[y] > rnk[x])
swap(x, y);
parent[y] = x;
}
// Function to find bridges
function dfsBridges(a, par)
{
vis[a] = true ;
// Initialize in time and
// low value
In[a] = low[a] = timer++;
for (let i = 0; i < v[a].length; i++)
{
if (v[a][i] == par)
continue ;
if (vis[v[a][i]])
// Update the low value
// of the parent
low[a] = Math.min(low[a], In[v[a][i]]);
else
{
// Perform DFS on its child
// updating low if the child
// has connection with any
// ancestor
dfsBridges(v[a][i], a);
low[a] = Math.min(low[a], low[v[a][i]]);
if (In[a] < low[v[a][i]])
// Bridge found
bridges.push([v[a][i], a]);
// Otherwise
else
// Find union between parent
// and child as they
// are in same component
union_set(v[a][i], a);
}
}
}
// Function to find diameter
// of the tree for storing
// max two depth child
function dfsDiameter(a, par)
{
let x = 0, y = 0;
for (let i = 0; i < g[a].length; i++)
{
if (g[a][i] == par)
continue ;
let mx = dfsDiameter(g[a][i], a);
// Finding max two depth
// from its children
if (mx > x)
{
y = x;
x = mx;
}
else if (mx > y)
y = mx;
}
// Update diameter with the
// sum of max two depths
diameter = Math.max(diameter,
x + y);
// Return the maximum depth
return x + 1;
}
// Function to find maximum
// bridges between
// any two nodes
function findMaxBridges()
{
for (let i = 0; i <= n; i++)
{
parent[i] = i;
rnk[i] = 1;
}
// DFS to find bridges
dfsBridges(1, 0);
// If no bridges are found
if (bridges.length == 0)
return 0;
let head = -1;
// Iterate over all bridges
for (let i = 0; i < bridges.length; i++)
{
// Find the endpoints
let a = find_set(bridges[i][0]);
let b = find_set(bridges[i][1]);
// Generate the tree with
// bridges as the edges
g[a].push(b);
g[b].push(a);
// Update the head
head = a;
}
diameter = 0;
dfsDiameter(head, 0);
// Return the diameter
return diameter;
}
/*
Graph =>
1 ---- 2 ---- 3 ---- 4
| |
5 ---- 6
*/
n = 6;
m = 6;
for (let i = 0; i < v.length; i++)
v[i] = [];
for (let i = 0; i < g.length; i++)
g[i] = [];
v[1].push(2);
v[2].push(1);
v[2].push(3);
v[3].push(2);
v[2].push(5);
v[5].push(2);
v[5].push(6);
v[6].push(5);
v[6].push(3);
v[3].push(6);
v[3].push(4);
v[4].push(4);
let ans = findMaxBridges();
document.write(ans + "</br>" );
// This code is contributed by mukesh07. </script> |
Output:
2
Time Complexity: O(N + M)
Auxiliary Space: O(N + M)
Recommended Articles
5. Convert the undirected graph into directed graph such that there is no path of length greater than 1
18. Minimum cost of path between given nodes containing at most K nodes in a directed and weighted graph