Tarjan 算法

一.算法简介

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

我们定义:

如果两个顶点可以相互通达,则称两个顶点强连通(strongly connected)。如果有向图G的每两个顶点都强连通,称G是一个强连通图。有向图的极大强连通子图,称为强连通分量(strongly connected components)。

例如:在上图中,{1 , 2 , 3 , 4 } , { 5 } ,  { 6 } 三个区域可以相互连通,称为这个图的强连通分量。

Tarjan算法是基于对图深度优先搜索的算法,每个强连通分量为搜索树中的一棵子树。搜索时,把当前搜索树中未处理的节点加入一个堆栈,回溯时可以判断栈顶到栈中的节点是否为一个强连通分量。

再Tarjan算法中,有如下定义。

DFN[ i ] : 在DFS中该节点被搜索的次序(时间戳)

LOW[ i ] : 为i或i的子树能够追溯到的最早的栈中节点的次序号

当DFN[ i ]==LOW[ i ]时,为i或i的子树可以构成一个强连通分量。

二.算法图示

以1为Tarjan 算法的起始点,如图

顺次DFS搜到节点6

回溯时发现LOW[ 5 ]==DFN[ 5 ] ,  LOW[ 6 ]==DFN[ 6 ] ,则{ 5 } , { 6 } 为两个强连通分量。回溯至3节点,拓展节点4.

拓展节点1 , 发现1再栈中更新LOW[ 4 ],LOW[ 3 ] 的值为1

回溯节点1,拓展节点2

自此,Tarjan Algorithm 结束,{1 , 2 , 3 , 4 } , { 5 } ,  { 6 } 为图中的三个强连通分量。

不难发现,Tarjan Algorithm 的时间复杂度为O(E+V).

三.算法模板

void Tarjan ( int x ) {
dfn[ x ] = ++dfs_num ;
low[ x ] = dfs_num ;
vis [ x ] = true ;//是否在栈中
stack [ ++top ] = x ;
for ( int i=head[ x ] ; i!= ; i=e[i].next ){
int temp = e[ i ].to ;
if ( !dfn[ temp ] ){
Tarjan ( temp ) ;
low[ x ] = gmin ( low[ x ] , low[ temp ] ) ;
}
else if ( vis[ temp ])low[ x ] = gmin ( low[ x ] , dfn[ temp ] ) ;
}
if ( dfn[ x ]==low[ x ] ) {//构成强连通分量
vis[ x ] = false ;
color[ x ] = ++col_num ;//染色
while ( stack[ top ] != x ) {//清空
color [stack[ top ]] = col_num ;
vis [ stack[ top-- ] ] = false ;
}
top -- ;
}
}

Tarjan 详解的更多相关文章

  1. LCA离线算法Tarjan详解

    离线算法也就是需要先把所有查询给保存下来,最后一次输出结果. 离线算法是基于并查集实现的,首先就是初始化P[i] = i. 接下来对于每个点进行dfs: ①首先判断是否有与该点有关的查询,如果当前该点 ...

  2. Tarjan算法详解

    Tarjan算法详解 今天偶然发现了这个算法,看了好久,终于明白了一些表层的知识....在这里和大家分享一下... Tarjan算法是一个求解极大强联通子图的算法,相信这些东西大家都在网络上百度过了, ...

  3. Tarjan求有向图强连通详解

    Tarjan求有向图强连通详解 注*该文章为转发,原文出处已经不得而知 :first-child { margin-top: 0; } blockquote > :last-child { ma ...

  4. Tarjan 算法详解

    一个神奇的算法,求最大连通分量用O(n)的时间复杂度,真实令人不可思议. 废话少说,先上题目 题目描述: 给出一个有向图G,求G连通分量的个数和最大连通分量. 输入: n,m,表示G有n个点,m条边 ...

  5. trie字典树详解及应用

    原文链接    http://www.cnblogs.com/freewater/archive/2012/09/11/2680480.html Trie树详解及其应用   一.知识简介        ...

  6. 算法笔记--sg函数详解及其模板

    算法笔记 参考资料:https://wenku.baidu.com/view/25540742a8956bec0975e3a8.html sg函数大神详解:http://blog.csdn.net/l ...

  7. Linq之旅:Linq入门详解(Linq to Objects)

    示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...

  8. 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)

    一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...

  9. EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解

    前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...

随机推荐

  1. (转)机器学习——深度学习(Deep Learning)

    from:http://blog.csdn.net/abcjennifer/article/details/7826917 Deep Learning是机器学习中一个非常接近AI的领域,其动机在于建立 ...

  2. 为什么要用babel-polyfill

    1.为什么要用babel-polyfill Babel默认只转换新的JavaScript句法(syntax),而不转换新的API,比如 Iterator.Generator.Set.Maps.Prox ...

  3. 从RAID看垂直伸缩到水平伸缩的演化

    磁盘的读写过程,最消耗时间的地方就是在磁盘中磁道寻址的过程,而一旦寻址完成,写入数据的速度很快. 连续写入:写入只寻址一次 存储位置与逻辑位置相邻 不用多次寻址 随机写入:每写一次 便寻址一次 增加了 ...

  4. PHP AES/ECB 128加密

    class Security { public static function encrypt($input, $key) { $key=md5($key.md5($key)); $size = mc ...

  5. codeforces986F Oppa Funcan Style Remastered【线性筛+最短路】

    容易看出是用质因数凑n 首先01个因数的情况可以特判,2个的情况就是ap1+bp2=n,b=n/p2(mod p1),这里的b是最小的特解,求出来看bp2<=n则有解,否则无解 然后剩下的情况最 ...

  6. PV、UV、VV、IP是什么意思?

    PV.UV.VV.IP作为网站分析中最常见的基础指标,能够从宏观概括性地衡量网站的整体运营状况,也是检测网站运营是否正常的最直观的指标. 1.VV(来访次数/访问次数):VisitView 记录所有访 ...

  7. iphone6 iphone6 plus 放大显示模式高分辨率模式问题

    分为兼容模式和高分辨率模式. 兼容模式 当你的 app 没有提供 3x 的 LaunchImage 时,系统默认进入兼容模式,大屏幕一切按照 320 宽度渲染,屏幕宽度返回 320:然后等比例拉伸到大 ...

  8. mac搭建TensorFlow环境

    1.首先安装Anaconda,下载地址:https://www.anaconda.com/download/#macos,根据需要下载所需的版本. 2.安装TensorFlow,安装命令:pip in ...

  9. 初次学习DropWizard框架——解决maven打包时出现没有主清单属性的问题

    笔者因为公司的项目需要,开始接触DropWizard框架,照着官网https://www.dropwizard.io/0.9.2/docs/getting-started.html撸了一遍. 工具为I ...

  10. BZOJ 1047: [HAOI2007]理想的正方形 单调队列瞎搞

    题意很简明吧? 枚举的矩形下边界和右端点即右下角,来确定矩形位置: 每一个纵列开一个单调队列,记录从 i-n+1 行到 i 行每列的最大值和最小值,矩形下边界向下推移的时候维护一下: 然后在记录的每一 ...