Tarjan Algorithm for Directed Graph strongly connected components
[Digraph strongly connected component]
In directed graph G, if at least one path exists between two vertices, the two vertices are calledStrongly Connected(Stronugly connected ). If each vertex of directed graph G is strongly connected, G is calledStrongly Connected Graph. A very large strongly connected subgraph of A digraph of a non-strongly connected graph, calledStrongly Connected Component(Strongly CTED components ).
In, the subgraph {1, 2, 3, 4} is a strongly connected component, because the vertex is reachable between 2, 2, 3, and 4. {5} and {6} are also two strongly connected components.
Based on the definition, we use bidirectional traversal to obtain the intersection to obtain the strongly connected component. The time complexity is O (n ^ 2 + M ). A better method is the kosaraju algorithm or the Tarjan algorithm. The time complexity of the two algorithms is O (n + M ). This document describes the Tarjan algorithm.
[Tarjan algorithm]
The Tarjan algorithm is based on the image depth-first search algorithm. Each strongly connected component is a subtree in the search tree. When searching, add unprocessed nodes in the current search tree to a stack. When backtracking, you can determine whether the nodes on the stack are a strongly connected component.
Define dfn (u) as the node u search order number (timestamp), low (u) the sequence number of the earliest node in the stack that can be traced back to the U or U subtree. Can be derived from the definition,
Low (u) = min {dfn (u), low (v), (u, v) is the branch edge, U is the parent node dfn (V) of V, (u, v) is the backward edge pointing to the node in the stack (non-cross edge )}
When dfn (u) = low (u), all nodes in the Child tree with u as the root are a strongly connected component.
The pseudo-code of the algorithm is as follows:
Tarjan (u) {dfn [u] = low [u] = ++ index // set the sequence number and low initial value stack for node u. push (u) // push node u into stack for each (u, v) in E // enumerate each side if (V is not visted) // If node V has not been accessed by Tarjan (v) // continue to find low [u] = min (low [u], low [v]) else if (V in S) // If node v is still in the stack, low [u] = min (low [u], dfn [v]) if (dfn [u] = low [u]) // If the node u is the root of the strongly connected component, repeat v = S. pop // roll back V to stack, print V until (u = V) for a vertex in the strongly connected component )}
Next, we will demonstrate the algorithm flow.
From Node 1 to DFS, add the traversal nodes to the stack. When node u = 6 is found, dfn [6] = low [6] finds a strongly connected component. Stack back to u = V, {6} is a strongly connected component.
Return to node 5. dfn [5] = low [5] is found. After stack rollback, {5} is a strongly connected component.
Return to node 3, search for node 4, and add node 4 to the stack. It is found that node 4 has a backward edge to node 1, and node 1 is still in the stack, so low [4] = 1. Node 6 is out of the stack, () is the cross edge, 3 is returned, () is the branch edge, so low [3] = low [4] = 1.
Go back to node 1 and Access Node 2. The access edges (2, 4) and 4 are still in the stack, so low [2] = dfn [4] = 5. After 1 is returned, dfn [1] = low [1] is found, and all nodes in the stack are taken out to form a connected component {1, 3, 4, 2 }.
So far, the algorithm has ended. After this algorithm, all three strongly connected components {1, 3, 4, 2}, {5}, {6} in the graph are obtained }.
It can be found that each vertex is accessed once during the running of the Tarjan algorithm, and only once in and out of the stack, each side is accessed only once, therefore, the time complexity of this algorithm is O (n + M ).
There is also a powerful Algorithm for Finding the strongly connected component of a directed graph, namely the kosaraju algorithm. Kosaraju is based on the two DFS methods for Directed Graphs and their inverse graphs, and its time complexity is O (n + M ). Compared with the Trajan algorithm, the kosaraju algorithm may be slightly more intuitive. However, Tarjan only needs to perform DFS for the source image once, and does not need to create inverse graphs, which is more concise. In actual tests, the running efficiency of the Tarjan algorithm is about 30% higher than that of the kosaraju algorithm. In addition, the Tarjan algorithm is closely related to the Tarjan Algorithm for Finding undirected graph's dual-connected components (cut points and bridges. Learning the Tarjan algorithm also helps you to deeply understand the Tarjan Algorithm for dual-connected components. The two can be compared and combined.
The Tarjan algorithm used to calculate the strongly connected component of a directed graph is named after its inventor Robert Tarjan. Robert Tarjan also invented the Tarjan Algorithm for the dual-connected component and the offline Tarjan Algorithm for the recent public ancestor. He expressed his high respect for Tarjan.
Appendix: C ++ program of the Tarjan Algorithm
void tarjan(int i){ int j; DFN[i]=LOW[i]=++Dindex; instack[i]=true; Stap[++Stop]=i; for (edge *e=V[i];e;e=e->next) { j=e->t; if (!DFN[j]) { tarjan(j); if (LOW[j]<LOW[i]) LOW[i]=LOW[j]; } else if (instack[j] && DFN[j]<LOW[i]) LOW[i]=DFN[j]; } if (DFN[i]==LOW[i]) { Bcnt++; do { j=Stap[Stop--]; instack[j]=false; Belong[j]=Bcnt; } while (j!=i); }}void solve(){ int i; Stop=Bcnt=Dindex=0; memset(DFN,0,sizeof(DFN)); for (i=1;i<=N;i++) if (!DFN[i]) tarjan(i);}