You are on page 1of 18

4/13/2018 Biconnected Components Tutorials & Notes | Algorithms | HackerEarth


Signup and get free access to 100+ Tutorials and Practice Problems Start Now
4

LIVE EVENTS
All Tracks  Algorithms  Graphs  Biconnected Components

Algorithms

 Solve any problem to achieve a rank


View Leaderboard

Topics: Biconnected Components 

Biconnected Components
TUTORIAL PROBLEMS

Pre-Requisite: Articulation Points

Before Biconnected Components, let's rst try to understand what a Biconnected Graph is and
how to check if a given graph is Biconnected or not.

A graph is said to be Biconnected if:

1. It is connected, i.e. it is possible to reach every vertex from every other vertex, by a simple
path.
2. Even after removing any vertex the graph remains connected.

For example, consider the graph in the following gure

https://www.hackerearth.com/practice/algorithms/graphs/biconnected-components/tutorial/ 1/18
4/13/2018 Biconnected Components Tutorials & Notes | Algorithms | HackerEarth

The given graph is clearly connected. Now try removing the vertices one by one and observe.
Removing any of the vertices does not increase the number of connected components. So the
given graph is Biconnected.
Now consider the following graph which is a slight modi cation in the previous graph.

https://www.hackerearth.com/practice/algorithms/graphs/biconnected-components/tutorial/ 2/18
4/13/2018 Biconnected Components Tutorials & Notes | Algorithms | HackerEarth

In the above graph if the vertex 2 is removed, then here's how it will look:

https://www.hackerearth.com/practice/algorithms/graphs/biconnected-components/tutorial/ 3/18
4/13/2018 Biconnected Components Tutorials & Notes | Algorithms | HackerEarth

Clearly the number of connected components have increased. Similarly, if vertex 3 is removed
there will be no path left to reach vertex 0 from any of the vertices 1, 2, 4 or 5. And same goes for
vertex 4 and 1. Removing vertex 4 will disconnect 1 from all other vertices 0, 2, 3 and 4. So the
graph is not Biconnected.

Now what to look for in a graph to check if it's Biconnected. By now it is said that a graph is
Biconnected if it has no vertex such that its removal increases the number of connected
components in the graph. And if there exists such a vertex then it is not Biconnected. A vertex
whose removal increases the number of connected components is called an Articulation Point.

So simply check if the given graph has any articulation point or not. If it has no articulation point
then it is Biconnected otherwise not. Here's the pseudo code:

time = 0
function isBiconnected(vertex, adj[][], low[], disc[], parent[], visited[], V)
disc[vertex]=low[vertex]=time+1
time = time + 1
visited[vertex]=true
child = 0
for i = 0 to V
if adj[vertex][i] == true
if visited[i] == false
child = child + 1
?

https://www.hackerearth.com/practice/algorithms/graphs/biconnected-components/tutorial/ 4/18
4/13/2018 Biconnected Components Tutorials & Notes | Algorithms | HackerEarth

parent[i] = vertex
result = isBiconnected(i, adj, low, disc, visited, V, time)
if result == false
return false
low[vertex] = minimum(low[vertex], low[i])
if parent[vertex] == nil AND child > 1
return false
if parent[vertex] != nil AND low[i] >= disc[vertex]
return false
else if parent[vertex] != i
low[vertex] = minimum(disc[i], low[vertex])
return true

The code above is exactly same as that for Articulation Point with one di erence that it returns
false as soon as it nds an Articulation Point.
The image below shows how the DFS tree will look like for the graph in Fig. 2 according to the
algorithm, along with the value of the arrays and .

https://www.hackerearth.com/practice/algorithms/graphs/biconnected-components/tutorial/ 5/18
4/13/2018 Biconnected Components Tutorials & Notes | Algorithms | HackerEarth

Clearly for vertex 4 and its child 1, , so that means 4 is an articulation point. The
algorithm returns false as soon as it discovers that 4 is an articulation point and will not go on to
check for vertices 0, 2 and 3. Value of for all vertices is just shown for clari cation.
Following image shows DFS tree, value of arrays and for graph in Fig.1

Clearly there does not exists any vertex , such that , i.e. the graph has no
articulation point, so the algorithm returns true, that means the graph is Biconnected.

Now let's move on to Biconnected Components. For a given graph, a Biconnected Component, is
one of its subgraphs which is Biconnected. For example for the graph given in Fig. 2 following are
4 biconnected components in the graph

https://www.hackerearth.com/practice/algorithms/graphs/biconnected-components/tutorial/ 6/18
4/13/2018 Biconnected Components Tutorials & Notes | Algorithms | HackerEarth

Biconnected components in a graph can be determined by using the previous algorithm with a
slight modi cation. And that modi cation is to maintain a Stack of edges. Keep adding edges to
the stack in the order they are visited and when an articulation point is detected i.e. say a vertex
has a child such that no vertex in the subtree rooted at has a back edge ( )
then pop and print all the edges in the stack till the is found, as all those edges including
the edge will form one biconnected component.

time = 0
function DFS(vertex, adj[][], low[], disc[], parent[], visited[], V, stack)
disc[vertex]=low[vertex]=time+1
time = time + 1
visited[vertex]=true
child = 0
for i = 0 to V
if adj[vertex][i] == true
if visited[i] == false
child = child + 1
?
push edge(u,v) to stack
https://www.hackerearth.com/practice/algorithms/graphs/biconnected-components/tutorial/ 7/18
4/13/2018 Biconnected Components Tutorials & Notes | Algorithms | HackerEarth

parent[i] = vertex
DFS(i, adj, low, disc, visited, V, time, stack)
low[vertex] = minimum(low[vertex], low[i])
if parent[vertex] == nil AND child > 1
while last element of stack != (u,v)
print last element of stack
pop from stack
print last element of stack
pop from stack
if parent[vertex] != nil AND low[i] >= disc[vertex]
while last element of stack != (u,v)
print last element of stack
pop from stack
print last element of stack
pop from stack
else if parent[vertex] != i AND disc[i] < low[vertex]
low[vertex] = disc[i]
push edge(u,v) to stack

fuction biconnected_components(adj[][], V)
for i = 0 to V
if visited[i] == false
DFS(i, adj, low, disc, parent, visited, V, time, stack)
while stack is not empty
print last element of stack
pop from stack

Let's see how it works for graph shown in Fig.2.


First it nds is false so it starts with vertex 0 and rst discovers the edge 0-3 and
pushes it in the stack.

Then with 3 it nds the edge 3-2 and pushes that in stack

With 2 it nds the edge 2-4 and pushes that in stack

https://www.hackerearth.com/practice/algorithms/graphs/biconnected-components/tutorial/ 8/18
4/13/2018 Biconnected Components Tutorials & Notes | Algorithms | HackerEarth

For 4 it rst nds edge 4-1 and pushes that in stack

It then discovers the fact that i.e. discovers that 4 is an articulation point. So all
the edges inserted after the edge 4-1 along with edge 4-1 will form rst biconnected component.
So it pops and print the edges till last edge is 4-1 and then prints that too and pop it from the
stack
Then it discovers the edge 4-5 and pushes that in stack

For 5 it discovers the back edge 5-2 and pushes that in stack

After that no more edge is connected to 5 so it goes back to 4. For 4 also no more edge is
connected and also .
Then it goes back to 2 and discovers that , that means 2 is an articulation point.
That means all the edges inserted after the edge 4-2 along with the edge 4-2 will form the second
biconnected component. So it print and pop all the edges till last edge is 4-2 and then print and
?
pop that too.
https://www.hackerearth.com/practice/algorithms/graphs/biconnected-components/tutorial/ 9/18
4/13/2018 Biconnected Components Tutorials & Notes | Algorithms | HackerEarth

Then it goes to 3 and discovers that 3 is an articulation point as so it print and


pops till last edge is 3-2 and the print and pop that too. That will form the third biconnected
component.

Now nally it discovers that for edge 0-3 also so it pops it from the stack and
print it as the fourth biconnected component.
Then it checks value of other vertices and as for all vertices it is true so the algorithm
terminates.
So ulitmately the algorithm discovers all the 4 biconnected components shown in Fig.6.
Time complexity of the algorithm is same as that of DFS. If is the number of vertices and is
the number of edges then complexity is .

Contributed by: Vaibhav Jaimini

Did you nd this tutorial helpful?



 YES

 NO

TEST YOUR UNDERSTANDING

Biconnected Components

Given a graph having N vertices and M edges, count the number of biconnected components
having odd number of vertices and even number of vertices.

Input:
First line consists of two space separated integers N and M.
M lines follow each containing two space separated integers X and Y denoting there is an edge
between vertices X and Y.

Output:
Print two space separated integers where rst integer denotes the number of biconnected
components having odd number of vertices and second integer denotes number of biconnected
components having even number of vertices.

Constraints:
1 ≤ N ≤ 10
?

https://www.hackerearth.com/practice/algorithms/graphs/biconnected-components/tutorial/ 10/18
4/13/2018 Biconnected Components Tutorials & Notes | Algorithms | HackerEarth

1≤M≤
0≤ <N

SAMPLE INPUT  

4 4
0 1
1 2
2 3
3 1

SAMPLE OUTPUT  

1 1

Enter your code or Upload your code as le. Save C (gcc 5.4.0)  
1 /*
2 // Sample code to perform I/O:
3 #include <stdio.h>
4
5 int main(){
6 int num;
7 scanf("%s", &num); // Reading input from STDIN
8 printf("Input number is %d.\n", num); // Writing output to STDOUT
9 }
10
11 // Warning: Printing unwanted or ill-formatted data to output will cause the t
12 */
13
14 // Write your code here
15

1:1

 Press Ctrl-space for autocomplete suggestions.


 Provide custom input

COMPILE & TEST SUBMIT

https://www.hackerearth.com/practice/algorithms/graphs/biconnected-components/tutorial/ 11/18
4/13/2018 Biconnected Components Tutorials & Notes | Algorithms | HackerEarth

COMMENTS (11)  SORT BY: Relevance 

Login/Signup to Comment

Mrinal Verma  Edited 10 个月前

why the condition " parent[vertex] != nil AND low[i] >= disc[vertex]" is not working but instead this
works low[i]>=disc[vertex]) need help
 1 vote  Reply  Message  Permalink

nipun753 9 个月前

the node from where dfs is started will not be counted as it doesn't have any ancestor that 's
why u r 1st condition won't be working remember biconnected component doesn't have any
articulation point
 2 votes  Reply  Message  Permalink

nipun753 9 个月前

i hope u understand my point of view


 2 votes  Reply  Message  Permalink

Gvs Akhil 1 年前

For the code to print the bi-connected components, Shouldn't the only condition be (
low[i]>=disc[vertex]) regardless if vertex is a root node or not?
Otherwise it will not nd the edge 0-3.
 2 votes  Reply  Message  Permalink

Deepanshu Vaid 1 年前

children>1 is not necessary for nding the bi-connected components please correct that
 1 vote  Reply  Message  Permalink

Ravi Kumar Tahlan 1 个月前

C++ working code(Use only for reference)


==================================
#include<bits/stdc++.h>
#de ne mk(a,b) make_pair(a,b)
#de ne pii pair< int , int>
using namespace std;
bool visited[11];
bool adj[11][11];
int dis[11],low[11];
int tym = 0;
int parent[11]={0};
stack< pii > st;
int eve=0,odd=0;
void calculate(pii p1,pii p2){
set< int > counter;
pii temp;
if(!st.empty())
do{
temp = st.top();
counter.insert(temp. rst);
counter.insert(temp.second);
st.pop();
}while(!st.empty() && (temp != p1 && temp != p2));

int len = counter.size();


if(len > 0)
if(len%2 == 0)
eve += 1;
else
odd += 1;
} ?
void dfs(int ver, int v){
https://www.hackerearth.com/practice/algorithms/graphs/biconnected-components/tutorial/ 12/18
4/13/2018 Biconnected Components Tutorials & Notes | Algorithms | HackerEarth

visited[ver] = true;
low[ver] = tym;
dis[ver] = tym;
int child = 0;
tym += 1;
for(int i = 0;i < v; i++){
if(adj[ver][i] == true){
if(visited[i] == false){
parent[i] = ver;
child += 1;
st.push(mk(ver,i));
dfs(i,v);
low[ver] = min(low[ver],low[i]);
if(parent[ver] == -1 && child > 1){
pii p1 = mk(ver,i);
pii p2 = mk(i,ver);
calculate(p1,p2);
}
if( parent[ver] != i && dis[ver] <= low[i] ){
pii p1 = mk(ver,i);
pii p2 = mk(i,ver);
calculate(p1,p2);
}
}
else if(parent[ver] != i && low[ver] > dis[i] ){
low[ver] = dis[i];
st.push(mk(ver,i));
}
}
}
}
void biconnected_components(int n){
parent[0] = -1;
for(int i = 0; i < n ; i++){
if(!visited[i]){
dfs(i,n);
}
}
set< int > counter;
while(!st.empty()){
pii temp = st.top();
st.pop();
counter.insert(temp. rst);
counter.insert(temp.second);
}
if(counter.size()>0){

if(counter.size() % 2 == 0)
eve += 1;
else
odd =+ 1;
}
}
int main(){
int n,m,a,b;
cin>>n>>m;
while(m--){
cin>>a>>b;
adj[a][b] = true;
adj[b][a] = true;
}
biconnected_components(n);
cout<<odd<<" "<<eve;
return 0; ?
}
https://www.hackerearth.com/practice/algorithms/graphs/biconnected-components/tutorial/ 13/18
4/13/2018 Biconnected Components Tutorials & Notes | Algorithms | HackerEarth

 1 vote  Reply  Message  Permalink

Gurpreet Singh 10 个月前

#include<bits/stdc++.h>
using namespace std;
#de ne pb(a) push_back(a)
#de ne mp(a,g) make_pair(a,g)
const int MAX = 10005;
int par[MAX] = {0},child[MAX]={0},low[MAX] = {0},tym[MAX]={0};
bool visit[MAX]={0},isCut={0};
static int t=0;
stack <pair <int,int> > bc;
vector <int> a[MAX];
int odd=0,even=0;
void BCdfs(int s){
visit[s] = true;
low[s]=tym[s]=t++;
for(int i=0;i<a[s].size();i++){
int v = a[s][i];
if(!visit[v]){
par[v] = s;
child[s]++;
bc.push(mp(s,v));
BCdfs(v);

low[s] = min(low[s],low[v]);
if((tym[s]==1 and child[s]>1)||( low[v]>=tym[s])){
set<int> nodes;
while(bc.top(). rst !=s || bc.top().second !=v){
nodes.insert(bc.top(). rst);
nodes.insert(bc.top().second);
bc.pop();
}
nodes.insert(bc.top(). rst);
nodes.insert(bc.top().second);
bc.pop();
if(nodes.size()!=0 and nodes.size()&1)odd++;
else even++;
}
}
else if(v!=par[s] && tym[v]<low[s]){
low[s] = min(low[s],tym[v]);
bc.push(mp(s,v));
}
}
}
int main(){
int n,m,x,y;cin>>n>>m;
while(m--){
cin>>x>>y;
a[x+1].pb(y+1);
a[y+1].pb(x+1);
}
par[1] = -1;
for(int i=1;i<=n;i++){
if(!visit[i])
BCdfs(i);
}
set <int> nodes;
while(!bc.empty()){
cout<<bc.top(). rst<<" "<<bc.top().second<<"\n";
nodes.insert(bc.top(). rst);
nodes.insert(bc.top().second); ?
bc.pop();

https://www.hackerearth.com/practice/algorithms/graphs/biconnected-components/tutorial/ 14/18
4/13/2018 Biconnected Components Tutorials & Notes | Algorithms | HackerEarth

if(nodes.size()!=0 and nodes.size()&1)odd++;


else if(nodes.size()!=0 ) even++;

cout<<odd<<" "<<even;

return 0;
}
 0 votes  Reply  Message  Permalink

Alex Smn 10 个月前

else if parent[vertex] != i AND disc[i] < low[vertex] should be else if parent[vertex] != i AND disc[i] <
disc[vertex]
 0 votes  Reply  Message  Permalink

Pranav Sarv Pathak  Edited 4 个月前


If i is already visited before..
And is now appearing as an edge with vertex also...
Then surely disc [i] will always be <disc [vertex]....(because as i is visited before thus also
Discovered before)
The condn given disc [i]<low [vertex] is correct
 0 votes  Reply  Message  Permalink

Maharshi Arun Singh 8 个月前

//AC Code
#include <iostream>
#include <stack>
#include <queue>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <climits>
#include <string>
#include <unordered_map>
#include <map>
#include <set>
#include <ctime>
#include <algorithm>
#include <cstring>
using namespace std;
int odd=0;
int even=0;
void dfs(int u, vector<bool>& visited, vector<int>& disc, vector<int>& low,
int parent, stack<pair<int, int> >& stk, vector<vector<int> >& adjList){
static int time=1;
disc[u] = low[u] = time++;
visited[u] = true;
int child=0;
int count=0;
for (auto& ele: adjList[u]){
if (!visited[ele]){
child++;
stk.push({u, ele});
dfs(ele, visited, disc, low, u, stk, adjList);
low[u] = min(low[u], low[ele]);

if ((parent==-1 && child>1) || (parent!=-1 && low[ele]>=disc[u])){


while (stk.top(). rst != u && stk.top().second != ele){
stk.pop();
count++;
}
?
stk.pop();

https://www.hackerearth.com/practice/algorithms/graphs/biconnected-components/tutorial/ 15/18
4/13/2018 Biconnected Components Tutorials & Notes | Algorithms | HackerEarth

if (count&1) odd++;
else even++;
}
}else if (ele != parent && disc[ele]<low[u]){
low[u] = disc[ele];
stk.push({u, ele});
}
}
}
int main() {
int n, m;
cin >> n >> m;
vector<vector<int> > adjList(n);
for (int i=0;i<m;i++){
int a, b;
cin >> a >> b;
adjList[a].push_back(b);
adjList[b].push_back(a);
}

vector<bool> visited(n, false);


vector<int> disc(n, INT_MAX);
vector<int> low(n, INT_MAX);
stack<pair<int, int> > stk;
for (int i=0;i<n;i++){
if (!visited[i]){
int count=0;
dfs(i, visited, disc, low, -1, stk, adjList);
while (!stk.empty()){
count++;
stk.pop();
}
if (count != 0)
if (count&1) odd++;
else even++;
}
}

cout << odd << " " << even << endl;
return 0;
}
 0 votes  Reply  Message  Permalink

Abhishek Tiwari 7 个月前

I am using set to store vertices in biconnected component, I have inserted some debug
statement, value for count and set size are di erent. What wrong am i doing in following code-
#include <bits/stdc++.h>
#de ne VI vector<int>
#de ne PII pair<int,int>
#de ne VVI vector<VI >
#de ne pb push_back
#de ne mp make_pair
using namespace std;
VVI adj_list;
VI low,parent, s_time;
vector<bool> visit;
stack<PII > bicon;
int timei=0;
int even=0,odd=0;
void nd_bc(int V, int E, int u){
timei+=1;
s_time[u]=low[u]=timei;
int child=0;
?
visit[u]=true;

https://www.hackerearth.com/practice/algorithms/graphs/biconnected-components/tutorial/ 16/18
4/13/2018 Biconnected Components Tutorials & Notes | Algorithms | HackerEarth

int count=0;
for(unsigned int i=0;i<adj_list[u].size();i++){
int v=adj_list[u][i];
if(!visit[v]){
child+=1;
parent[v]=u;
if(u<v)
bicon.push(mp(u,v));
else
bicon.push(mp(v,u));

nd_bc(V,E,v);
low[u]=min(low[u],low[v]);
if((parent[u]==-1 && child>1)||(parent[u]!=-1 && low[v]>=s_time[u])){
PII po=bicon.top();
set<int> vert;
if(u>v)
swap(u,v);
while(po. rst!=u && po.second!=v){
vert.insert(po. rst);
vert.insert(po.second);
bicon.pop();
po=bicon.top();
count++;
}
bicon.pop();
vert.insert(u);
vert.insert(v);
cout<<"$ "<<vert.size()<<" "<<count<<endl;
if(vert.size()%2)
odd++;
else
even++;
vert.clear();
}
}
else if(v!=parent[u] && low[u]>s_time[v]){
low[u]=s_time[v];
if(u<v)
bicon.push(mp(u,v));
else
bicon.push(mp(v,u));
}
}
}
int main()
{
int V,E;
cin>>V>>E;
adj_list.resize(V);
low.assign(V,INT_MAX);
parent.assign(V,-1);
s_time.assign(V,0);

visit.assign(V,false);

for(int i=0;i<E;i++){
int u,v;
cin>>u>>v;
adj_list[u].push_back(v);
adj_list[v].pb(u);
}

for(int i=0;i<V;i++) ?
{
https://www.hackerearth.com/practice/algorithms/graphs/biconnected-components/tutorial/ 17/18
4/13/2018 Biconnected Components Tutorials & Notes | Algorithms | HackerEarth

if(!visit[i])
{ nd_bc(V,E,i);
set<int> vert;
int count=0;
while(!bicon.empty()){
PII po=bicon.top();
bicon.pop();
vert.insert(po. rst);
vert.insert(po.second);
count++;
}
cout<<"# "<<vert.size()<<" "<<count<<endl;
if(!vert.empty())
{if(vert.size()%2)
odd++;
else
even++;
}
vert.clear();
}
}
cout<<odd<<" "<<even<<endl;

return 0;
}
 0 votes  Reply  Message  Permalink

About Us Innovation Management

Technical Recruitment University Program

Developers Wiki Blog

Press Careers

Reach Us

Site Language: English | Terms and Conditions | Privacy |© 2018 HackerEarth

https://www.hackerearth.com/practice/algorithms/graphs/biconnected-components/tutorial/ 18/18

You might also like