Tarjan算法详解理解集合
【功能】
Tarjan算法的用途之一是,求一个有向图G=(V,E)里极大强连通分量。强连通分量是指有向图G里顶点间能互相到达的子图。而如果一个强连通分量已经没有被其它强通分量完全包含的话,那么这个强连通分量就是极大强连通分量。
【算法思想】
用dfs遍历G中的每个顶点,通dfn[i]表示dfs时达到顶点i的时间,low[i]表示i所能直接或间接达到时间最小的顶点。(实际操作中low[i]不一定最小,但不会影响程序的最终结果)
程序开始时,time初始化为0,在dfs遍历到v时,low[v]=dfn[v]=time++,
v入栈(这里的栈不是dfs的递归时系统弄出来的栈)扫描一遍v所能直接达到的顶点k,如果 k没有被访问过那么先dfs遍历k,low[v]=min(low[v],low[k]);如果k在栈里,那么low[v]=min(low[v],dfn[k])(就是这里使得low[v]不一定最小,但不会影响到这里的low[v]会小于dfn[v])。扫描完所有的k以后,如果low[v]=dfn[v]时,栈里v以及v以上的顶点全部出栈,且刚刚出栈的就是一个极大强连通分量。
【大概的证明】
1. 在栈里,当dfs遍历到v,而且已经遍历完v所能直接到达的顶点时,low[v]=dfn[v]时,v一定能到达栈里v上面的顶点:
因为当dfs遍历到v,而且已经dfs递归调用完v所能直接到达的顶点时(假设上面没有low=dfn),这时如果发现low[v]=dfn[v],栈上面的顶点一定是刚才从顶点v递归调用时进栈的,所以v一定能够到达那些顶点。
2 .dfs遍历时,如果已经遍历完v所能直接到达的顶点而low[v]=dfn[v],我们知道v一定能到达栈里v上面的顶点,这些顶点的low一定小于 自己的dfn,不然就会出栈了,也不会小于dfn[v],不然low [v]一定小于dfn[v],所以栈里v以其v以上的顶点组成的子图是一个强连通分量,如果它不是极大强连通分量的话low[v]也一定小于dfn[v](这里不再详细说),所以栈里v以其v以上的顶点组成的子图是一个极大强连通分量。
【时间复杂度】
因为所有的点都刚好进过一次栈,所有的边都访问的过一次,所以时间复杂度为O(n+m)
【可看证明】
若存在边<i, j>且遍历到它的时候j在栈中,那么i和j可能存在三种关系:
(1)i是j的祖先;
(2)j是i的祖先;
(3)i和j无前后关系。
对于情况(1),必有dfn[j]>dfn[i],因此不必考虑;
对于情况(2),<i, j>是逆向边,显然i、j处于同一个强连通分支;
对于情况(3):<i, j>是横叉边。显然i、j必然在同一棵搜索树中(因为搜索树的根结点肯定满足low=dfn),设p=LCA(i, j),由于从p到j的路径上木有low=dfn的结点(否则j已经出栈了),所以j必然可以到达p,又因为p可以到达i,所以j也可以到达i,又因为存在边<i, j>,所以i、j处于同一个强连通分支,这样就需要在计算low[i]的时候把dfn[j]考虑进去,而不能让i及其所有后代成为一个强连通分支。
【外援】https://www.byvoid.com/blog/scc-tarjan
Tarjan算法详解理解集合的更多相关文章
- Tarjan算法详解
Tarjan算法详解 今天偶然发现了这个算法,看了好久,终于明白了一些表层的知识....在这里和大家分享一下... Tarjan算法是一个求解极大强联通子图的算法,相信这些东西大家都在网络上百度过了, ...
- Tarjan 算法详解
一个神奇的算法,求最大连通分量用O(n)的时间复杂度,真实令人不可思议. 废话少说,先上题目 题目描述: 给出一个有向图G,求G连通分量的个数和最大连通分量. 输入: n,m,表示G有n个点,m条边 ...
- ACM(图论)——tarjan算法详解
---恢复内容开始--- tarjan算法介绍: 一种由Robert Tarjan提出的求解有向图强连通分量的线性时间的算法.通过变形,其亦可以求解无向图问题 桥: 割点: 连通分量: 适用问题: 求 ...
- Tarjan算法 详解+心得
Tarjan算法是由Robert Tarjan(罗伯特·塔扬,不知有几位大神读对过这个名字) 发明的求有向图中强连通分量的算法. 预备知识:有向图,强连通. 有向图:由有向边的构成的图.需要注意的是这 ...
- 【转】AC算法详解
原文转自:http://blog.csdn.net/joylnwang/article/details/6793192 AC算法是Alfred V.Aho(<编译原理>(龙书)的作者),和 ...
- KM算法详解[转]
KM算法详解 原帖链接:http://www.cnblogs.com/zpfbuaa/p/7218607.html#_label0 阅读目录 二分图博客推荐 匈牙利算法步骤 匈牙利算法博客推荐 KM算 ...
- BM算法 Boyer-Moore高质量实现代码详解与算法详解
Boyer-Moore高质量实现代码详解与算法详解 鉴于我见到对算法本身分析非常透彻的文章以及实现的非常精巧的文章,所以就转载了,本文的贡献在于将两者结合起来,方便大家了解代码实现! 算法详解转自:h ...
- kmp算法详解
转自:http://blog.csdn.net/ddupd/article/details/19899263 KMP算法详解 KMP算法简介: KMP算法是一种高效的字符串匹配算法,关于字符串匹配最简 ...
- 机器学习经典算法详解及Python实现--基于SMO的SVM分类器
原文:http://blog.csdn.net/suipingsp/article/details/41645779 支持向量机基本上是最好的有监督学习算法,因其英文名为support vector ...
随机推荐
- Linux下CGroup使用说明梳理
CGroup 介绍CGroup 是 Control Groups 的缩写,是 Linux 内核提供的一种可以限制.记录.隔离进程组 (process groups) 所使用的物力资源 (如 cpu m ...
- WPF基础——Application
一.Application介绍 WPF中的Application对象用来进行一些全局的行为和操作,并且每个 Domain (应用程序域)中仅且只有一个 Application 实例存在.WPF App ...
- 各种同步方法性能比较(synchronized,ReentrantLock,Atomic)
5.0的多线程任务包对于同步的性能方面有了很大的改进,在原有synchronized关键字的基础上,又增加了ReentrantLock,以及各种Atomic类.了解其性能的优劣程度,有助与我们在特定的 ...
- PowerDesigner打开设计文件后提示failed to read the fileXXX的解决办法
擦,一身盗汗.一向的设计信息都在设计图里!竟然坏了,坏了!!!!! 惊.怒.悲 固然可以经由过程数据库当前状况反向工程.然则那么注解.我写的提示这些器材都邑消散. 比来的备份是10天前,恢复也会有必然 ...
- Linux内核分析——第八周学习笔记20135308
第八周 进程的切换和系统的一般执行过程 一.进程切换的关键代码switch_to分析 1.进程调度与进程调度的时机分析 (1)进程分类 第一种分类 I/O-bound:等待I/O CPU-bound: ...
- 信息安全系统设计基础第一次实验报告 20135201&&20135306&&20135307
信息安全系统设计基础实验 班级: 201353 姓名:张忻 张嘉琪 黄韧 学号:20135301 20135307 20135306 实验日期:2015.11.10 实验名称: S3C2410的lin ...
- 学习笔记——Maven实战(五)自动化Web应用集成测试
自动化集成测试的角色 本专栏的上一篇文章讲述了Maven与持续集成的一些关系及具体实践,我们都知道,自动化测试是持续集成必不可少的一部分,基本上,没有自动化测试的持续集成,都很难称之为真正的持续集成. ...
- ArrayList List<T> T[] Array
ArrayList 其实就是一个存储obj列表的类 ArrayList 接受 null 作为有效值并且允许重复的元素. 不保证会对 ArrayList 排序. 在执行需要对 ArrayList ...
- iOS 后台运行 类型
iOS后台运行,需要有特定的类型才可以进行.这些内容并不是一直不变的,苹果也在逐步的更新这些内容. 本文内容是2015年11月03日时苹果支持的后台运行类型. 这是官方连接地址 其中较为重要的是下面这 ...
- WPF开发时光之痕日记本(二)—— MVVM基类
当我们用MVVM的时候要实现INotifyPropertyChanged,每次都要实现这个接口比较麻烦,所以基类的作用就体现出来了.代码如下: public class ViewModelBase : ...