为找到根结点,我们给每个结点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