Tarjan算法(发现强连通图的算法)
Tarjan算法也是用来发现强连通子图的算法,是Kosaraju算法的改进,算法复杂度是,算法比较简单,位代码和java实现代码如下:
package cn.edu.dlut.wisdom;
import it.unimi.dsi.fastutil.ints.*;
import it.unimi.dsi.fastutil.objects.*;
import it.unimi.dsi.webgraph.*;
import java.util.Comparator;
/**
** @author You Wang* Input: Graph G = (V, E)* index = 0 // DFS node number counter* S = empty // An empty stack of nodes* forall v in V do* if (v.index is undefined) // Start a DFS at each node* tarjan(v) // we haven't visited yet** procedure tarjan(v)* v.index = index // Set the depth index for v* v.lowlink = index* index = index + 1* S.push(v) // Push v on the stack* forall (v, v') in E do // Consider successors of v* if (v'.index is undefined) // Was successor v' visited?* tarjan(v') // Recurse* v.lowlink = min(v.lowlink, v'.lowlink)* else if (v' is in S) // Was successor v' in stack S?* v.lowlink = min(v.lowlink, v'.index )* if (v.lowlink == v.index) // Is v the root of an SCC?* print "SCC:"* repeat* v' = S.pop* print v'* until (v' == v)*/public class Tarjan {private ImmutableGraph graph;
private ObjectAVLTreeSet<IntAVLTreeSet> sccs;
private int[] indexs;private int[] lowLinks;private int numNodes;private IntArrayList stack;
private int index;public Tarjan(ImmutableGraph graph) {
this.graph = graph;
numNodes = graph.numNodes();}public void tarjan(int v) {indexs[v] = index;lowLinks[v] = index;index++;stack.push(v);for(int successor : graph.successorArray(v)) {if(indexs[successor] == -1) {
tarjan(successor);lowLinks[v] = Math.min(lowLinks[v], lowLinks[successor]);}else if(stack.contains(successor))lowLinks[v] = Math.min(lowLinks[v], indexs[successor]);}if (lowLinks[v] == indexs[v]) {
int n;
IntAVLTreeSet component = new IntAVLTreeSet();
do {
n = stack.popInt();component.add(n);} while(n != v);
sccs.add(component);}}public ObjectAVLTreeSet<IntAVLTreeSet> compute() {
Comparator cmp = new Comparator() {
public int compare(Object o1, Object o2) {if(o1 instanceof IntAVLTreeSet && o2 instanceof IntAVLTreeSet) {IntAVLTreeSet s1 = (IntAVLTreeSet)o1;IntAVLTreeSet s2 = (IntAVLTreeSet)o2;if (s1.size() != s2.size())
return s1.size() - s2.size();
else
{int[] a1 = s1.toIntArray();
int[] a2 = s2.toIntArray();
for (int i = 0; i < a1.length; i++)if (a1[i] != a2[i])
return a1[i] - a2[i];
return 0;
}}else
throw new IllegalArgumentException("The argument must be an IntAVLTreeSet");}};sccs = new ObjectAVLTreeSet<IntAVLTreeSet>(cmp);
indexs = new int[numNodes];for(int i = 0; i < numNodes; i++)indexs[i] = -1;lowLinks = new int[numNodes];stack = new IntArrayList();
index = 0;for(int i = 0; i < numNodes; i++)if(indexs[i] == -1)
tarjan(i);return sccs;
}}
本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名小橋流水(包含链接)。如您有任何疑问或者授权方面的协商,请给我发邮件。