为找到根结点,我们给每个结点v一个深度优先搜索标号v.index,表示它是第几个被访问的结点。此外,每个结点v还有一个值v.lowlink,表示从v出发经有向边可到达的所有结点中最小的index。显然v.lowlink总是不大于v.index,且当从v出发经有向边不能到达其他结点时,这两个值相等。v.lowlink在深度优先搜索的过程中求得,v是强连通分量的根当且仅当v.lowlink = v.index。
algorithm tarjan is
input: 图 G = (V, E)
output: 以所在的强连通分量划分的顶点集
index := 0
S := empty // 置栈为空
for each v in V do
if (v.index is undefined)
strongconnect(v)
end if
function strongconnect(v)
// 将未使用的最小index值作为结点v的index
v.index := index
v.lowlink := index
index := index + 1
S.push(v)
// 考虑v的后继结点
for each (v, w) in E do
if (w.index is undefined) then
// 后继结点w未访问,递归调用
strongconnect(w)
v.lowlink := min(v.lowlink, w.lowlink)
else if (w is in S) then
// w已在栈S中,亦即在当前强连通分量中
v.lowlink := min(v.lowlink, w.index)
end if
// 若v是根则出栈,并求得一个强连通分量
if (v.lowlink = v.index) then
start a new strongly connected component
repeat
w := S.pop()
add w to current strongly connected component
until (w = v)
output the current strongly connected component
end if
end function
下面附上实现源代码:
/*
* Author : YANG Xiangyu
*
* Hint: tarjan scc
*
* The Chinese University of Hong Kong
*/
package cyclefinder;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
import java.util.Stack;
import java.util.Vector;
public class TarjanSCC{
class Node{//内部类定义节点
Vector<Integer> adj;
}
Node[] graph;
Stack<Integer> stack;
int indices;
boolean[] inStack;
int[] index;
int[] lowLink;
int[] component;
Set<Integer> nodeset;
int numComponents;
int n,m;
public TarjanSCC(){
graph=new Node[16000];
inStack=new boolean[16000];
index=new int[16000];
lowLink=new int[16000];
component=new int[16000];
inStack=new boolean[16000];
stack=new Stack<Integer>();
nodeset=new HashSet<Integer>();
for(int i=0;i<component.length;++i){
component[i]=0xffffffff;
}
for(int i=0;i<graph.length;++i){
graph[i]=new Node();
graph[i].adj=new Vector<Integer>();
}
}
public void strongconnect(int v){
index[v]=indices;
lowLink[v]=indices;
indices++;
stack.push(v);
inStack[v]=true;
for(int j=0;j<graph[v].adj.size();++j){
int w=graph[v].adj.get(j);
if(index[w]==0){
strongconnect(w);
lowLink[v]=Math.min(lowLink[v],lowLink[w]);
}else if(inStack[w]){
lowLink[v]=Math.min(lowLink[v],index[w]);
}
}
if(lowLink[v]==index[v]){
int w=0;
do{
w=stack.pop();
component[w]=numComponents;
inStack[w]=false;
}while(v!=w&&!stack.empty());
numComponents++;
}
}
public void tarjanFunc(){
indices=1;
while(!stack.empty()){
stack.pop();
}
Object[] v=nodeset.toArray();
for(int i=0;i<v.length;++i){
lowLink[(int) v[i]]=0;
index[(int) v[i]]=0;
inStack[(int) v[i]]=false;
}
numComponents=0;
for(int i=0;i<v.length;++i){
if(index[(int) v[i]]==0){
strongconnect((int) v[i]);
}
}
}
public void input(String path) throws FileNotFoundException{
Scanner input=new Scanner(new File(path));
n=input.nextInt();
m=input.nextInt();
int a=0,b=0;
for(int i=0;i<m;++i){
a=input.nextInt();
b=input.nextInt();
graph[a].adj.add(b);
nodeset.add(a);
}
input.close();
}
public void prints(String path) throws FileNotFoundException
{
PrintStream output = new PrintStream(path);
for(int i=0;i<16000;++i){
output.print(component[i]+" "+i+" ");
for(int j=0;j<graph[i].adj.size();++j){
output.print(graph[i].adj.get(j)+" ");
}
output.println();
}
System.out.println(numComponents);
output.println(numComponents);
output.close();
}
public static void main(String[] args) throws FileNotFoundException{
TarjanSCC tarjanscc=new TarjanSCC();
tarjanscc.input("C:/circleOrderedId.txt");
tarjanscc.tarjanFunc();
tarjanscc.prints("C:/tarjansccresults.txt");
}
}原文地址:http://blog.csdn.net/yangxiangyuibm/article/details/39293961