Tarjan 算法详解

摘要:
TarjanTarjan算法是一种求解有向图强连通分量的算法,它能做到线性时间的复杂度。如果要理解Tarjan,我们首先要了解一下,什么叫做强连通。算法思想简解Tarjan是在dfs的基础上将每一个强连通分量当做搜索树种的一个子树的遍历方法。算法图解在这张图中我们从节点1开始遍历,依次将1,3,5加入堆栈。然后,Tarjan算法就这么简单的就结束了。很显然,Tarjan算法的复杂度只有O(E+V)啦。算法模板双手奉上我丑陋的代码。

刚学的一个 新算法,终于有时间来整理一下了。

想必都对著名的 ‘太监’ 算法早有耳闻了吧。

Tarjan

Tarjan 算法是一种求解有向图强连通分量的算法,它能做到线性时间的复杂度。

实现是基于DFS爆搜,深度优先搜索一张有向图。!注意!是有向图。然后根据树,堆栈,打标记等种种神奇扯淡方法来完成拆解一个图的工作。

如果要理解Tarjan,我们首先要了解一下,什么叫做强连通。


强连通

首先,我们将可以相互通达的两个点,称这两个点是强连通的。

自然,对于一张图,它的每两个点都强连通,那么这张图就是一张强连通图。

而一张有向图中的极大强连通子图就被命名为强连通分量。

那么,举个栗子吃吧。

Tarjan 算法详解第1张盗图小丸子光荣上线,come from 百度

对于上面的那张有向图来说,{1,2,3,4},{5},{6}分别相互连通,是这张图的三个强连通分量。


算法思想简解

Tarjan是在dfs的基础上将每一个强连通分量当做搜索树种的一个子树的遍历方法。

那么我们就可以在搜索的时候,将当前的树中没有访问过的节点加入堆栈,然后在回溯的时候判断栈顶到其中的节点是否是一个强连通分量。

故而我们在遍历的时候,定义如下变量来记录我们的遍历过程。

1.dfn[i]=时间戳(节点i被搜索的次序)

2.low[i]=i或i的子树所能寻找到的栈中的节点序号。

所以,当dfn[i]==low[i]时,i或i的子树可以构成一个强连通分量。


算法图解(盗图愉悦)

Tarjan 算法详解第2张

在这张图中我们从节点1开始遍历,依次将1, 3,5加入堆栈。当搜索到节点6时,发现没有可以向前走的路,开始回溯。

回溯的时候会发现low[5]=dfn[5],low[6]=dfn[6],那么{5},{6}分别是两个强连通分量。

直到回溯至节点3,拓展出节点4.

Tarjan 算法详解第3张

结果自然就是拓展到了节点1,发现1在栈中,于是就用1来更新low[4]=low[3]=1;

然后回溯节点1,将点2加入堆栈中。

Tarjan 算法详解第4张

然后,Tarjan算法就这么简单的就结束了。

很显然,Tarjan算法的复杂度只有O(E+V)啦。线性愉快。


算法模板

双手奉上我丑陋的代码。

void Tar(intnow) {
    dfn[now]=low[now]=++ti;
    sk[++p]=now;
    vis[now]=1;
    for(int i=head[now];i;i=d[i].nxt) {
        int nx=d[i].to;
        if(!dfn[nx]) {
            Tar(nx);
            low[now]=min(low[now],low[nx]);
        }
        else if(vis[nx]) low[now]=min(low[now],dfn[nx]);
    }
    if(low[now]==dfn[now]) {
        while(sk[p+1]!=now) {
            val[now]+=val[sk[p]];vis[sk[p]]=0;
            --p;
        }
        val[now]>>=1;
    }
}

希望可以很简洁易懂!!

谢谢。

免责声明:文章转载自《Tarjan 算法详解》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇C#实现文件的压缩和解压缩Windows Server 2008 R2 免费使用 7200天 激活下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

深度优先生成树及其应用

在上一篇博客判断有向图是否有圈中从递归的角度简单感性的介绍了如何修改深度优先搜索来判断一个有向图是否有圈。事实上, 它的实质是利用了深度优先生成树(depth-first spanning tree)的性质。那么什么是深度优先生成树?顾名思义,这颗树由深度优先搜索而生成的,由于无向图与有向图的深度优先生成树有差别,下面将分别介绍。 一. 无向图的深度优先生...

TarJan 算法求解有向连通图强连通分量

[有向图强连通分量] 在有向图G中,如果两个 顶点间至少存在一条路径,称两个顶点强连通(strongly connected)。如果有向图G的每两个顶点都强连通,称G是一个强连通图。非强连通图有向图的极大强连通子图,称为强连通分量(strongly connected components)。 下图中,子图{1,2,3,4}为一个强连通分量,因为顶点1,...

Tarjan求割点

概述 在一个无向图中,若删除某个点u后连通分量数目增加,则称点u为该无向图的一个割点(cut vertex) 引理 无向连通图DFS树 从一个节点出发进行DFS,将后访问的结点设为前访问结点的孩子,DFS经过的边叫做DFS树的树边(tree edge),第一次处理时从后代(descendant)指向祖先(ancestor)的边叫做返祖边(back edge...

Tarjan的学习笔记 求割边求割点

博主图论比较弱,搜了模版也不会用。。。 所以决心学习下tarjan算法。 割点和割边的概念不在赘述,tarjan能在线性时间复杂度内求出割边。 重要的概念:时间戟,就是一个全局变量clock记录访问结点的时间。一个无向图dfs会形成一个森林,当图只有一个连通分量时,就只有一棵树。 由于在无向图中,除了树边,其他都是反向边。可以画个图感受一下,可以反证的,如...