0% found this document useful (0 votes)
79 views9 pages

Articulation Points and Bridges Tutorials & Notes - Algorithms - HackerEarth

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
79 views9 pages

Articulation Points and Bridges Tutorials & Notes - Algorithms - HackerEarth

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 9

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

LIVE EVENTS
All Tracks  Algorithms  Graphs  Articulation Points and Bridges

Algorithms

 Solve any problem to achieve a rank


View Leaderboard

Topics: Articulation Points and Bridges 

Articulation Points and Bridges


TUTORIAL PROBLEMS

Articulation Point

In a graph, a vertex is called an articulation point if removing it and all the edges associated
with it results in the increase of the number of connected components in the graph. For
example consider the graph given in following gure.

?
If in the above graph, vertex 1 and all the edges associated with it, i.e. the edges 1-0, 1-2 and
1-3 are removed, there will be no path to reach any of the vertices 2, 3 or 4 from the vertices 0
and 5, that means the graph will split into two separate components. One consisting of the
vertices 0 and 5 and another one consisting of the vertices 2, 3 and 4 as shown in the following
gure.

?
Likewise removing the vertex 0 will disconnect the vertex 5 from all other vertices. Hence the
given graph has two articulation points: 0 and 1.

Articulation Points represents vulnerabilities in a network. In order to nd all the articulation


points in a given graph, the brute force approach is to check for every vertex if it is an
articulation point or not, by removing it and then counting the number of connected
components in the graph. If the number of components increases then the vertex under
consideration is an articulation point otherwise not.

Here's the pseudo code of the brute force approach, it returns the total number of articulation
points in the given graph.

function find_articulation_points(adj[][], V)
count = 0
for i = 0 to V
visited[i] = false
initial_val = 0
for i = 0 to V
if visited[i] == false
DFS(adj, V, visited, i)
initial_val = initial_val+1

for i=0 to V
for j = 0 to V
visited[j] = false
copy[j] = adj[i][j]
adj[i][j]=adj[j][i]=0

nval = 0
for j= 0 to V
if visited[j] == false AND j != i
nval = nval + 1
DFS(adj, n, visited, j)
if nval > initial_val
count = count + 1
for j= 0 to V
adj[i][j] = adj[j][i] = copy[j]
return count

The above algorithm iterates over all the vertices and in one iteration applies a Depth First
Search to nd connected components, so time complexity of above algorithm is
, where V is the number of vertices and E is the number of edges in the
graph.

Clearly the brute force approach will fail for bigger graphs.

?
There is an algorithm that can help nd all the articulation points in a given graph by a single
Depth First Search, that means with complexity , but it involves a new term called
"Back Edge" which is explained below:

Given a DFS tree of a graph, a Back Edge is an edge that connects a vertex to a vertex that is
discovered before it's parent. For example consider the graph given in Fig. 1. The gure given
below depicts a DFS tree of the graph.

In the above case, the edge 4 - 2 connects 4 to an ancestor of its parent i.e. 3, so it is a Back
Edge. And similarly 3 - 1 is also a Back edge. But why bother about Back Edge? Presence of a
back edge means presence of an alternative path in case the parent of the vertex is removed.
Suppose a vertex is having a child such that none of the vertices in the subtree rooted at
have a back edge to any vertex discovered before , that means if vertex is removed then
there will be no path left for vertex or any of the vertices present in the subtree rooted at
vertex v to reach any vertex discovered before , that implies, the subtree rooted at vertex
will get disconnected from the entire graph, and thus the number of components will increase
and will be counted as an articulation point. On the other hand, if the subtree rooted at
vertex has a vertex that has back edge that connects it to a vertex discovered before , say
, then there will be a path for any vertex in subtree rooted at to reach even after removal?
of , and if that is the case with all the children of , then will not count as an articulation
point.

So ultimately it all converges down to nding a back edge for every vertex. So, for that apply a
DFS and record the discovery time of every vertex and maintain for every vertex the earliest
discovered vertex that can be reached from any of the vertices in the subtree rooted at . If a
vertex is having a child such that the earliest discovered vertex that can be reached from
the vertices in the subtree rooted at has a discovery time greater than or equal to , then
does not have a back edge, and thus will be an articulation point.

So, till now the algorithm says that if all children of a vertex are having a back edge, then
is not an articulation point. But what will happen when is root of the tree, as root does not
have any ancestors. Well, it is very easy to check if the root is an articulation point or not. If
root has more than one child than it is an articulation point otherwise it is not. Now how does
that help?? Suppose root has two children, and . If there had been an edge between
vertices in the subtree rooted at and those of the subtree rooted at , then they would
have been a part of the same subtree.

Here's the pseudo code of the above algorithm:

time = 0
function DFS(adj[][], disc[], low[], visited[], parent[], AP[], vertex, V)
visited[vertex] = true
disc[vertex] = low[vertex] = time+1
child = 0
for i = 0 to V
if adj[vertex][i] == true
if visited[i] == false
child = child + 1
parent[i] = vertex
DFS(adj, disc, low, visited, parent, AP,
i, n, time+1)
low[vertex] = minimum(low[vertex], low[i])
if parent[vertex] == nil and child > 1
AP[vertex] = true
if parent[vertex] != nil and low[i] >=
disc[vertex]
AP[vertex] = true
else if parent[vertex] != i
low[vertex] = minimum(low[vertex], disc[i])

Here's what everything means:

: It is an matrix denoting the adjacency matrix of the given graph.

?
: It is an array of elements which stores the discovery time of every vertex. It is
initialized by 0.

: It is an array of elements which stores, for every vertex , the discovery time of the
earliest discovered vertex to which or any of the vertices in the subtree rooted at is having
a back edge. It is initialized by INFINITY.

: It is an array of size which denotes whether a vertex is visited or not during the
DFS. It is initialized by false.

: It is an array of size which stores the parent of each vertex. It is initialized by NIL.

: It is an array of size . = true, if i th vertex is an articulation point.

: The vertex under consideration.

: Number of vertices.

: Current value of discovery time.

The above algorithm starts with an initial vertex say , marks it visited, record its discovery
time, , and since it is just discovered, the earliest vertex it is connected to is itself, so
is also set equal to vertex's discovery time.

It keeps a counter called to count the number of children of a vertex. Then the algorithm
iterates over every vertex in the graph and see if it is connected to , if it nds a vertex . that
is connected to , but has already been visited, then it updates the value to minimum of
and discovery time of i.e., .But if the vertex is not yet visited, then it sets the
to and calls the DFS again with . So the same things that just happened
with will happen for also. When that DFS call will return, will have the discovery time
of the earliest discovered vertex that can be reached from any vertex in the subtree rooted at
. So set to minimum of and itself. And nally if is not the root, it checks
whether is greater than or equal to , and if so, it marks as true. And if is
root it checks whether it has more than one child or not, and if so, it marks as true.

The following image shows the value of array and for DFS tree given in Fig. 3.

?
Clearly only for vertices 0 and 1, and , so these are the only
two articulation points in the given graph.

Bridges

An edge in a graph between vertices say and is called a Bridge, if after removing it, there
will be no path left between and . It's de nition is very similar to that of Articulation Points.
Just like them it also represents vulnerabilities in the given network. For the graph given in
Fig.1, if the edge 0-1 is removed, there will be no path left to reach from 0 to 1, similarly if edge
0-5 is removed, there will be no path left that connects 0 and 5. So in this case the edges 0-1
and 0-5 are the Bridges in the given graph.

The Brute force approach to nd all the bridges in a given graph is to check for every edge if it
is a bridge or not, by rst removing it and then checking if the vertices that it was connecting
are still connected or not. Following is pseudo code of this approach:

function find_bridges(adj[][], V, Edge[], E, isBridge[])


for i = 0 to E
?
adj[Edge[i].u][Edge[i].v]=adj[Edge[i].v][Edge[i].u]=0
for j = 0 to V
visited[j] = false
Queue.Insert(Edge[i].u])
visited[Edge[i].u] = true
check = false
while Queue.isEmpty() == false
x = Queue.top()
if x == Edge[i].v
check = true
BREAK
Queue.Delete()
for j = 0 to V
if adj[x][j] == true AND visited[j] == false
Queue.insert(j)
visited[j] = true
adj[Edge[i].u][Edge[i].v]=adj[Edge[i].v][Edge[i].u]=1
if check == false
isBridge[i] = true

The above code uses BFS to check if the vertices that were connected by the removed edge are
still connected or not. It does so for every edge and thus it's complexity is .
Clearly it will fail for big values of and .

To check if an edge is a bridge or not the above algorithm checks if the vertices that the edge
is connecting are connected even after removal of the edge or not. If they are still connected,
this implies existence of an alternate path. So just like in the case of Articulation Points the
concept of Back Edge can be used to check the existence of the alternate path. For any edge,
, (u having discovery time less than v), if the earliest discovered vertex that can be visited
from any vertex in the subtree rooted at vertex has discovery time strictly greater than that
of , then is a Bridge otherwise not. Unlike articulation point, here root is not a special
case. Following is the pseudo code for the algorithm:

time = 0
function DFS(adj[][], disc[], low[], visited[], parent[], vertex, n)
visited[vertex] = true
disc[vertex] = low[vertex] = time+1
child = 0
for i = 0 to n
if adj[vertex][i] == true
if visited[i] == false
child = child + 1
parent[i] = vertex
DFS(adj, disc, low, visited, parent, i, n,
time+1)
low[vertex] = minimum(low[vertex], low[i])
if low[i] > disc[vertex] ?
print vertex, i
else if parent[vertex] != i
low[vertex] = minimum(low[vertex], disc[i])

For graph given in Fig.1, the and value obtained for its DFS tree shown in Fig.3, by
the above pseudo code, will be the same as those obtained in case of articulation points. The
values of array and are shown in Fig.4. Clearly for only two edges i.e 0-1 and 0-5,
> and > , hence those are the only two bridges in the given graph.

Contributed by: Vaibhav Jaimini

About Us Innovation Management

Technical Recruitment University Program

Developers Wiki Blog

Press Careers

Reach Us

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

You might also like