美文网首页
图算法(二)Tarjan

图算法(二)Tarjan

作者: maxkibble | 来源:发表于2018-07-09 21:16 被阅读0次

在一次BFS或DFS中,我们其实并不能保证一定访问到图中的所有节点,因为有些图可能是不连通的。我们把从一个点出发,所有可达点的集合称为这个点所在的连通分量。给定一个无向图,我们找所有连通分量的方法叫做灌水法(Flood Fill),其实就是对当前未访问过的点做BFS/DFS,直到所有的点都被访问过1次。
Tarjan算法是为了解决有向图中类似的问题提出的。只不过有向图中我们可以定义强连通分量,有向图中一个强连通分量中的任意两个点u,v都是强连通的,即存在从u到v的路径,也存在从v到u的路径。

strong-connected.png

很明显,Flood Fill并不能用来求强连通分量。但只使用BFS/DFS,我们可以给出一个求给定点所在强连通分量的方法:1) 从该点出发做一次BFS/DFS;2) 把所有边反向,再从这个点做一次BFS/DFS;3) 把两次搜索访问的顶点集合做一次交,就可以得到该点所在的极大强连通分量。如果用这种方法求所有强连通分量的话,需要对每个点做两次BFS/DFS。更好的方法是Kosaraju算法或Tarjan算法,这里只介绍Tarjan,它只需要对图做一遍DFS。

在进入Tarjan算法之前,你需要明白对图做DFS可以得到一棵树,树的根节点是DFS的起点,每次从点u访问一个的点v,就引一条从u到v的边。

Tarjan算法中,图中每个节点维护两个属性:

  1. dfu(i):节点i在DFS中第dfu(i)个被访问到(时间戳);
  2. low(i):DFS搜索树中,以节点i为根节点的子树中的节点集合记为T(i)。T(i)中的点在原图中所指向的点的集合记为S(i)。S(i)中最小的时间戳就是low(i)。

Tarjan算法的描述如下:

  1. 初始化一个空的栈和一个每访问一个节点加1的计时器
  2. 对图做DFS,每次访问新的顶点时,设定dfn(i)为当前时间,把该节点压栈,接着求low(i):对于还没被访问的后继节点j,递归访问j,low(i) = min(low(i), low(j)),对于已经访问过的且在栈中的后继节点j,low(i) = min(low(i), dfn(j))。如果最终得到的low(i) = dfn(i),就把栈中当前节点以上的节点全部弹出,这些节点就是一个极大强连通分量

Tarjan算法只需要做一遍DFS,所以一定会终止,时间复杂度O(m+n)

C++实现:

void tarjan(int u) {
    dfn[u] = low[u] = ++cnt;
    st[++top] = u;
    instack[u] = true;

    for(Edge *p = e[u]; p; p = p->next) {
        int v = p->dst;
        if(!dfn[v]) {
            tarjan(v);
            low[u] = std::min(low[u], low[v]);
        }
        else if(instack[v])
            low[u] = std::min(low[u], dfn[v]);
    }
    
    if(dfn[u] == low[u]) {
        cluster++;
        int hd;
        do {
            hd = st[top--];
            instack[hd] = false;
            belong[hd] = cluster;
        }
        while(hd != u);
    }
}

(PS:一道经典的求强连通分量的题 Networks of School

相关文章

  • 图算法(二)Tarjan

    在一次BFS或DFS中,我们其实并不能保证一定访问到图中的所有节点,因为有些图可能是不连通的。我们把从一个点出发,...

  • tarjan算法

    tarjan算法前提 一个关于图的联通性的神奇算法。基于DFS(深度搜索)算法,深度优先搜索一张有向图。!注意!是...

  • ZJL的OI知识汇总图

    最后更新于:2018-07-15 亟待解决的问题:博弈论全部差分约束与Tarjan算法二分图全部ISAP算法和zk...

  • 图算法(一)遍历,拓扑排序

    本文介绍图的几种基本操作:BFS,DFS,求有向图连通分量的Tarjan算法以及拓扑排序。 图的表示 一张图是由若...

  • Tarjan学习笔记

    在最近学习中遇到了几次题解使用Tarjan的情况,便查了一些资料。 算法简介 一种由Robert Tarjan提出...

  • tarjan算法动态演示

    java swing写的tarjan算法[https://zhuanlan.zhihu.com/p/1019233...

  • Least Common Ancestor

    题目链接:最近公共祖先 树链剖分: Tarjan(离线)算法: 原创模板: RMQ-ST(在线)算法: 题目链接:...

  • 图论-----求割点

    求无向连通图割点(java)-------Tarjan算法 在无向连通图中,如果将其中一个点以及所有连接该点的边去...

  • Tarjan算法求强联通分量

    Tarjan算法求强联通分量基于对图的DFS: 表示节点在DFS搜索中是第几个被搜索到的(时间戳)。 表示从在DF...

  • Tarjan算法求割点,桥

    下面介绍中无向图中割点和桥的概念:割点:一个结点称为割点(或者割顶)当且仅当去掉该节点极其相关的边之后的子图不连通...

网友评论

      本文标题:图算法(二)Tarjan

      本文链接:https://www.haomeiwen.com/subject/azztpftx.html