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   小橋流水  阅读(294)  评论(0编辑  收藏  举报

编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述

导航

统计

点击右上角即可分享
微信分享提示