Note: The contents of this article are reproduced from http://www.cppblog.com/sosi/archive/2010/09/26/127797.html, on the one hand, there are many online Tarjan algorithm introduction, I don't think so. The simplicity of his article is straightforward or does not have a specific implementation. On the other hand, I also conveniently used Java to achieve a bit, so publish and share with you!
[Strong connected component of the graph]
In a direction diagram G, if there is at least one path between two vertices, the two vertices are strongly connected (strongly connected). If there is a strong connection to each of the two vertices of the graph G, G is a strongly connected graph. The maximal strongly connected subgraph of a undirected graph of a non strongly connected graph is called a strongly connected component (strongly connected components).
In the following figure, the child figure {1,2,3,4} is a strongly connected component because the vertex 1,2,3,4 22 is up to. {5},{6} is also two strong connected components respectively.
[Tarjan algorithm]
The Tarjan algorithm is based on the depth-first search algorithm, and each strong-connected component is a Shang tree in the search tree. When searching, the unhandled nodes in the current search tree are added to a stack, and backtracking can be used to determine whether the node in the stack is a strong connected component.
Define DFN (U) d records the time of search to the U, which is the first few search U. Low (U) is the order number of the nodes in the earliest stack that the subtree of U or u can trace back to.
algorithm pseudo code is as follows
Tarjan (U)
{
Dfn[u]=low[u]=++index//Set sequence number and low initial value for node U
Stack.push (U)//Push the node u into the Stack
For every (U, v) in E//enumerate each edge
If (V is not visted)//If node V has not been accessed
Tarjan (v)//continue looking down
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 node U is the root of a strongly connected component
Repeat
v = s.pop//V-back stack, a vertex for the strongly connected component
Print V
Until (u== v)
}
The next step is to demonstrate the algorithm flow. DFS is started from Node 1, and the nodes that are traversed are added to the stack. When the node u=6 was searched, Dfn[6]=low[6], a strong connected component was found. {6} is a strong connected component until the stack is u=v.
Return node 5, find Dfn[5]=low[5], after which {5} is a strong connected component.
Return to Node 3, continue searching to node 4, and add 4 to the stack. found that node 4 to Node 1 has a back edge, node 1 is still in the stack, so low[4]=1. Node 6 has been out of the stack, (4,6) is the cross side, returned 3, (3,4) for the edge of the tree, so low[3]=low[4]=1.
Go back to Node 1 and finally Access Node 2. Access Edge (2,4), 4 is still on the stack, so low[2]=dfn[4]=5. After returning 1, Discover Dfn[1]=low[1], take out all the nodes in the stack and form a connected component {1,3,4,2}.
At this point, the algorithm is over. Through this algorithm, we find out all three strong connected components {1,3,4,2},{5},{6} in the graph. It can be found that in the process of running the Tarjan algorithm, each vertex is accessed once, and only one stack is in and out, each edge is only accessed once, so the time complexity of the algorithm is O (n+m).
The algorithm Java implementation is as follows:
Tarjan class:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Stack;
public class Tarjan {
private int numOfNode;
Private list < ArrayList < integer > > graph; / / figure
Private list < ArrayList < integer > > result; / / save the most strongly connected graph
Private Boolean [] instack; / / whether the node is in the stack, because it is not convenient to find a node in the stack. This way to find fast
private Stack<Integer> stack;
private int[] dfn;
private int[] low;
private int time;//
public Tarjan(List< ArrayList<Integer> > graph,int numOfNode){
this.graph = graph;
this.numOfNode = numOfNode;
this.inStack = new boolean[numOfNode];
this.stack = new Stack<Integer>();
dfn = new int[numOfNode];
low = new int[numOfNode];
Arrays. Fill (DFN, - 1); / / set all elements of DFN to - 1, where DFN [i] = - 1 means I has not been accessed.
Arrays.fill(low, -1);
result = new ArrayList<ArrayList<Integer>>();
}
public List< ArrayList<Integer> > run(){
for(int i=0;i<numOfNode;i++){
if(dfn[i]==-1){
Tarjan (I);
}
}
return result;
}
public void tarjan(int current){
dfn[current]=low[current]=time++;
inStack[current]=true;
stack.push(current);
for(int i=0;i<graph.get(current).size();i++){
int next = graph.get(current).get(i);
If (DFN [next] = = - 1) {/ / - 1 means not accessed
tarjan(next);
low[current]=Math.min(low[current], low[next]);
}else if(inStack[next]){
low[current]=Math.min(low[current], dfn[next]);
}
}
if(low[current]==dfn[current]){
ArrayList<Integer> temp =new ArrayList<Integer>();
Int j = -1;
while(current!=j){
j = stack.pop();
inStack[j]=false;
Temp.add (J);
}
result.add(temp);
}
}
}
Test class:
Import java.util.ArrayList;
Import java.util.List;
Import Java.util.Stack;
public class Main {public
static void Main (string[] args) {
//create figure
int numofnode = 6;
list< arraylist<integer> > Graph = new arraylist<arraylist<integer>> ();
for (int i=0;i<numofnode;i++) {
graph.add (new arraylist<integer> ());
}
Graph.get (0). Add (1);
Graph.get (0). Add (2);
Graph.get (1). Add (3);
Graph.get (2). Add (3);
Graph.get (2). Add (4);
Graph.get (3). Add (0);
Graph.get (3). Add (5);
Graph.get (4). Add (5);
Call the Tarjan algorithm to find the maximal connected subgraph
Tarjan t = new Tarjan (graph, numofnode);
list< arraylist<integer> > result = T.run ();
Print result for
(int i=0;i<result.size (), i++) {for
(int j=0;j<result.get (i). Size (); j + +) {
System.out.print (Result.get (i). Get (J) + "");
}
System.out.println ();}}