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

时间: 2024-10-05 03:36:42

Tarjan算法详解理解集合的相关文章

Tarjan算法详解

Tarjan算法详解 [概念] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的极大强连通子图,称为强连通分量(strongly connected components). 下图中,子图{1,2,3,4}为一个强连通分量,因为顶点1,2,3,4两两可达.{5},{6}也分别是两个强连通分量. [功能] Tarjan算法的用途之一是,求一个有向图G=(V,E)里极大强连

ACM(图论)——tarjan算法详解

---恢复内容开始--- tarjan算法介绍: 一种由Robert Tarjan提出的求解有向图强连通分量的线性时间的算法.通过变形,其亦可以求解无向图问题 桥: 割点: 连通分量: 适用问题: 求解(有向图/无向图)的,桥,割点,环,回路等问题 整体思想: 如果我们欲要求解,桥的个数,割点的个数,环的数目,归根结底,是分析清楚一个图 有几个 环,每个环包含哪些节点,那些边. 而 tarjan算法就是做的这件事情,通过dfs遍历每一条边和节点,算出有几个环,每个环中有哪些节点.那么是如何做的呢

Tarjan算法详解(转)

思想: 做一遍DFS,用dfn[i]表示编号为i的节点在DFS过程中的访问序号(也可以叫做开始时间)用low[i]表示i节点DFS过程中i的下方节点所能到达的开始时间最早的节点的开始时间.初始时dfn[i]=low[i] 在DFS过程中会形成一搜索树.在搜索树上越先遍历到的节点,显然dfn的值就越小. DFS过程中,碰到哪个节点,就将哪个节点入栈.栈中节点只有在其所属的强连通分量已经全部求出时,才会出栈. 如果发现某节点u有边连到搜索树中栈里的节点v,则更新u的low 值为dfn[v](更新为l

并查集算法详解

更好的阅读体验 并查集算法详解 算法详解 维护类型 身为一个数据结构,我们的并查集,它的维护对象是我们的关注点. 并查集适合维护具有非常强烈的传递性质,或者是连通集合性质. 性质详解 传递性质 传递性,也就是具有传递效应的性质,比如说A传递给B一个性质或者条件,让B同样拥有了这个性质或者条件,那么这就是我们所说的传递性. 连通集合性质 连通集合性,和数学概念上的集合定义是差不多的, 比如说A和B同属一个集合,B和C同属一个集合,那么A,B,C都属于同一个集合.这就是我们所谓的连通集合性质. 算法

【转】AC算法详解

原文转自:http://blog.csdn.net/joylnwang/article/details/6793192 AC算法是Alfred V.Aho(<编译原理>(龙书)的作者),和Margaret J.Corasick于1974年提出(与KMP算法同年)的一个经典的多模式匹配算法,可以保证对于给定的长度为n的文本,和模式集合P{p1,p2,...pm},在O(n)时间复杂度内,找到文本中的所有目标模式,而与模式集合的规模m无关.正如KMP算法在单模式匹配方面的突出贡献一样,AC算法对于

机器学习经典算法详解及Python实现---朴素贝叶斯分类及其在文本分类、垃圾邮件检测中的应用

摘要: 朴素贝叶斯分类是贝叶斯分类器的一种,贝叶斯分类算法是统计学的一种分类方法,利用概率统计知识进行分类,其分类原理就是利用贝叶斯公式根据某对象的先验概率计算出其后验概率(即该对象属于某一类的概率),然后选择具有最大后验概率的类作为该对象所属的类.总的来说:当样本特征个数较多或者特征之间相关性较大时,朴素贝叶斯分类效率比不上决策树模型:当各特征相关性较小时,朴素贝叶斯分类性能最为良好.另外朴素贝叶斯的计算过程类条件概率等计算彼此是独立的,因此特别适于分布式计算.本文详述了朴素贝叶斯分类的统计学

KM算法详解[转]

KM算法详解 原帖链接:http://www.cnblogs.com/zpfbuaa/p/7218607.html#_label0 阅读目录 二分图博客推荐 匈牙利算法步骤 匈牙利算法博客推荐 KM算法步骤 KM算法标杆(又名顶标)的引入 KM流程详解 KM算法博客推荐 0.二分图 二分图的概念 二分图又称作二部图,是图论中的一种特殊模型. 设G=(V, E)是一个无向图.如果顶点集V可分割为两个互不相交的子集X和Y,并且图中每条边连接的两个顶点一个在X中,另一个在Y中,则称图G为二分图. 可以

机器学习经典算法详解及Python实现--聚类及K均值、二分K-均值聚类算法

摘要 聚类是一种无监督的学习(无监督学习不依赖预先定义的类或带类标记的训练实例),它将相似的对象归到同一个簇中,它是观察式学习,而非示例式的学习,有点像全自动分类.说白了,聚类(clustering)是完全可以按字面意思来理解的--将相同.相似.相近.相关的对象实例聚成一类的过程.机器学习中常见的聚类算法包括 k-Means算法.期望最大化算法(Expectation Maximization,EM,参考"EM算法原理").谱聚类算法(参考机器学习算法复习-谱聚类)以及人工神经网络算法

最短路算法 :Bellman-ford算法 &amp; Dijkstra算法 &amp; floyd算法 &amp; SPFA算法 详解

 本人QQ :2319411771   邮箱 : [email protected] 若您发现本文有什么错误,请联系我,我会及时改正的,谢谢您的合作! 本文为原创文章,转载请注明出处 本文链接   :http://www.cnblogs.com/Yan-C/p/3916281.html . 很早就想写一下最短路的总结了,但是一直懒,就没有写,这几天又在看最短路,岁没什么长进,但还是加深了点理解. 于是就想写一个大点的总结,要写一个全的. 在本文中因为邻接表在比赛中不如前向星好写,而且前向星效率并