The types of edges in a DFS of a directed graph:
Lemma. If (v,w) is a crossedge
then DFN[v] > DFN[w],
i.e., cross edges go from right to left.
A directed graph is strongly connected if there is a path from each vertex to each other vertex. A maximal subgraph that is strongly connected is called a strongly connected component (also called a strong component). Vertices x and y are in the same strong component if and only if there exists a path from x to y and there exists a path from y to x.
Lemma. If Gi = (Vi,Ei) is a strong component of directed graph G = (V,E) and S = (V,T) is a DFS forest for G then (Vi, Ei) intersect T) is a tree.
that is, the strong components are trees that are subgraphs of the spanning forest.
If we know the roots of all of the strong components in the spanning forest then we would know what the strong components were. By first deleting the subtrees that consist of other strong components that lie below v we would be left with the strong component headed by v.
Lemma. If the roots ri of the strong components Gi are listed in the order of completion of SEARCHB(ri) [ SEARCHB(ri) terminates before SEARCHB(ri+1) ] then Gi consists of those vertices that are descendents of ri but are not in any of G1... Gi-1.
To help find the roots, define LOWLINK(v) = the smallest numbered vertex in the same strong component as v that can be reached by going down some tree edges followed by at most one back or xross edge.
Then v is the root of a strong component iff LOWLINK(v) = DFN[v].
If v is not the root of a strong component then LOWLINK(v) < DFN[v]. This can be seen as follows. There is a path from v to the root of v's strong component. Let w be the first node on that path that is outside of v's subtree. DFN[w] < DFN[v] since cross-edges and backedges do that. w is in the same strong component as v since there is a path Root to v to w and there is a path w to Root to v.
We can express a recurrence relation on LOWLINK:
LOWLINK(v) = minimum x such that
either 1. x = DFN[v]
or 2. x = DFN[w], where (v,w) is a back or cross edge
or 3. x = LOWLINK[s], where s is a son of v
The strong components are found in a manner similar to biconnected components. The vertices are put on a stack and, when a root is found, the stack is popped.
COUNT := 0
forall vertices v do
FLAG[v] := "new"
ONSTACK[v] = "no"
STACK := Λ
while there exists a v s.t. FLAG[v] = "new" do
SEARCH(1)
SEARCH(v)
FLAG[v] := "old"
COUNT := COUNT + 1
DFN[v] := COUNT
1: LOWLINK[v] := DFN[v]
STACK ← v
ONSTACK[v] := "yes"
Let L[v] be the list of vertices s.t. (v,w) is an edge
while L[v] ≠ Λ do
w ⇐ L[v]
if FLAG[w] = "old" then
if (DFN[w] < DFN[v]) and (ONSTACK[w] = "yes") then
/** therefore a back or cross edge and not a forward edge **/
2: LOWLINK[v] := min{ LOWLINK[v], DFN[w] }
else /** FLAG[w] = "new" **/
SEARCH(w)
3: LOWLINK[v] := min{ LOWLINK[v], LOWLINK[w] }
if LOWLINK[v] = DFN[v] then
x ⇐ STACK
ONSTACK[x] := "no"
print x
while x ≠ v do
x ⇐ STACK
ONSTACK[x] := "no"
print x
print "end of strong component"
The time complexity of this algorithm is O(n + e).