Lecture 25. Strongly connected components of a digraph. 11/24/97.

===============================================================

25.1. Strongly connected components. In a digraph we define a strongly connected component to be a subgraph in which for any two vertices v,w there is a path from v to w and a path from w to v. Strong connectivity is an equivalence relation on the vertices of G. If G has only one strongly connected component, then G is said to be strongly connected. (figure 13).

Exercise 25.1.

a. Prove that strong connectivity is an equivalence relation on the vertices of a directed graph G.

b. Show that a directed graph G may have edges which are not in any of its strongly connected components.

Exercise 25.2. Find the strongly connected components of the graph G in figure 14.

Note that in a depth first search of a directed graph G we partition the edges of G into four classes:

1. tree edges, those which lead to new vertices visited for the first time

2. forward edges which go from ancestors to proper descendants but which are not tree edges

3. back edges which go from descendants to ancestors (and may go from a vertex to itself)

4. cross edges which go between vertices that are neither ancestors nor descendants of each other (figure 15).

The strongly connected components of a directed graph G can be found by a modification of depth first search which runs in time = O(max (|V|, |E|).

We assume that the vertices in G are labeled by their depth-first search numbers.

Lemma. If G(i) = (V(i), E(i) ) is a strongly connected component of a directed graph G and S = (V,T) is a depth-first spanning forest for G, then the vertices of G(i), with the edges common to T and E(i) form a tree.

Proof. Let v and w be vertices in V(i), v < w. Let P be a path in G(i) from v to w and let x be the lowest numbered vertex on P, possibly v itself. Now once P has reached a descendant of x it cannot leave the subtree of descendants of x, since only cross edges and back edges to vertices lower than x leave the subtree. Therefore w is a descendant of x. Also all vertices between x and w are descendants of x. Since x <= v < w, w must be a descendant of x. Since v and w were any two vertices in G(i), any two vertices in G(i) must have a common ancestor. Let r be the lowest number common ancestor of the vertices in G(i). Then any vertex on the spanning tree path from r to v is also in G(i).

This shows that we can find the strongly connected components of G by keeping track of the roots of the components in the order they are (last) found.

define

LOWLINK[v] = min (label of v, label of w, where w is in the set such that there is a cross edge or back edge from a descendant of v to w and the root of the strongly connected component containing w is an ancestor of v.

Lemma. If G is a directed graph, then a vertex v is the root of a strongly connected component of G if and only if LOWLINK[v] = v.

Proof. If v is the root of a strongly connected component and LOWLINK[v] < v, then there are vertices w and r such that w is reached by a cross or back edge from a descendant of v, r is the root of the strongly connected component containing w, r is an ancestor of v, and w < v. Now r is an ancestor of w, so r <= w. Thus r < v and so r is a proper ancestor of v. But there is a path from r to v and a path from v to r (going through w). So r and v are in the same strongly connected component. So v is not the root of a strongly connected component, which is a contradiction.

On the other hand, if LOWLINK[v] = v, then if v is not the root of the strongly connected component in which it lies, r, a proper ancestor of v, is the root. Thus there is a path P from v to r. Then the first edge of P from a descendant of v to a vertex w which is not a descendant of v is either a back edge to an ancestor of v or a cross edge to a vertex numbered lower that v. In each case w < v. Since r is an ancestor of v, there is a path from r to v. It goes actually from v to w to r. So r and w are in that same strongly connected component and LOWLINK[v] <= w < v, which is a contradiction.

Strongly connected component algorithm.

Set count = 1.

mark all v "unvisited".

initialize stack to be empty.

while there is a vertex v unvisited, sccsearch(v).

sccsearch(v)

mark v "visited"

dfsnum(v) = count

++count

lowlink[v] = dfsnum(v).

push v.

for each w in adjlist(v) do

if w is "unvisited" then

scsearch(w)

LOWLINK[v] = min(LOWLINK(v),LOWLINK(w)).

else

if dfsnum(w) < dfsnum(v) and w is on the stack then

LOWLINK[v] = min(dfsnum(w), LOWLINK[v]).

if LOWLINK[v] = dfsnum(v) then

repeat

pop x, print x

until x = v

write "end of strongly connected component"