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;
    }
}

posted on 2010-04-06 06:13  小橋流水  阅读(281)  评论(0编辑  收藏  举报

导航