Tarjan's strongly connected components algorithm

Pku 2186,2553,1236,2762,都是可以用强连通分量算法来解决的。Kosaraju的算法在大部分情况下还是够用的,至少对于这四个题时间都还行。但是既然有更好的算法,那也学习一下吧。

The algorithm takes a directed graph as input, and produces a partition of the graph's vertices into the graph's strongly connected components. Every vertex of the graph appears in a single strongly connected component, even if it means a vertex appears in a strongly connected component by itself (as is the case with tree-like parts of the graph, as well as any vertex with no successor or no predecessor).

算法的输入是一个有向图,产生一个图的强连通分量顶点划分。图的每个顶点都会出现在一个强连通分量当中,尽管这意味着一个强连通分量可能只有一个顶点。

The basic idea of the algorithm is this: a depth-first search begins from an arbitrary start node (and subsequent depth-first searches are conducted on any nodes that have not yet been found). The search does not explore any node that has already been explored. The strongly connected components form the subtrees of the search tree, the roots of which are the roots of the strongly connected components.

基本思想是:从任意一个结点出发深搜(后续的深搜要在未访问过的结点上进行)。不能搜索已经探索过的结点。强连通分量形成了搜索树,他们的根就是强连通分量的根。

The nodes are placed on a stack in the order in which they are visited. When the search returns from a subtree, the nodes are taken from the stack and it is determined whether each node is the root of a strongly connected component. If a node is the root of a strongly connected component, then it and all of the nodes taken off before it form that strongly connected component.

被访问的结点按顺序放进栈中。当从一个搜索树返回时,判断该点是否是一个强连通分量的根。如果该点是一个强连通分量的根,那么从栈提出相应的点就是一个强连通分量了。

The crux of the algorithm comes in determining whether a node is the root of a strongly connected component. The concept of the "root" applies only to this algorithm (outside of the algorithm, a strongly connected component has no single "root" node). The root node is simply the first node of the strongly connected component which is encountered during the depth-first traversal. When a node is identified as the root node, once recursion on its successors has finished, all nodes on the stack from the root upwards form a complete strongly connected component.

算法的关键是判断一个结点是否是强连通分量的根。根这个概念仅用于这个算法中(其余的算法中,没有这个概念)。这个根结点是在深搜时碰到当前强连通分量的第一个结点。当一个结点被确定为一个根时,一旦后续子女递归完成,那么从栈中找到所有的相关结点就是一个完整的强连通分量。

To find the root, each node is given a depth search index v.index, which numbers the nodes consecutively in the order in which they are discovered. In addition, each node is assigned a value v.lowlink that is equal to the index of some node reachable from v, and always less than v.index, or equal to v.index if no other node is reachable from v. Therefore v is the root of a strongly connected component if and only if v.lowlink == v.index. The value v.lowlink is computed during the depth first search such that it is always known when needed.

为了找到这个根,每个结点都赋一个搜索序列号v.index, 这个号是搜索的先后顺序。另外,每个结点都赋一个值v.lowlink. 这个值等于从v能够到达的结点的序列号的最小值。总是小于v.index,或者等于v.index. 只有当v.lowlink==v.index的时候,才是强连通分量的根结点。V.lowlink的值是实时更新的。

algorithm tarjan isinput: graph G = (V, E)output: set of strongly connected components (sets of vertices)index := 0S := emptyfor each v in V doif (v.index is undefined)strongconnect(v)end ifrepeatfunction strongconnect(v)// Set the depth index for v to the smallest unused indexv.index := indexv.lowlink := indexindex := index + 1S.push(v)// Consider successors of vfor each (v, w) in E doif (w.index is undefined) then// Successor w has not yet been visited; recurse on itstrongconnect(w)v.lowlink := min(v.lowlink, w.lowlink)else if (w is in S) then// Successor w is in stack S and hence in the current SCCv.lowlink := min(v.lowlink, w.index)end ifrepeat// If v is a root node, pop the stack and generate an SCCif (v.lowlink = v.index) thenstart a new strongly connected componentrepeatw := S.pop()add w to current strongly connected componentuntil (w = v)output the current strongly connected componentend ifend function

关于算法正确性的解析:正如文中所说,判断每个结点是否为根节点。也许看完之后还是有些疑惑。为什么会这样? 假如v是一个强连通分量的一个点,深搜的时候第一个访问到它。从v能够访问的所有的点,都会有lowlink连接到v。那么就说明了这些点就是一个强连通分量。

举个例子:

对于这样一副图,从1开始深搜,到6的时候不能再往下搜了,此时如果6能够链到之前搜过的结点,那么就会出现scc.很显然这里没有,所以它的low就是自己的搜索序列号了。然后剔除。

返回5,5也没有链到之前的点,剔除

返回3,3可继续搜,到4了,4链到1,则low[4] = 1. 然后low[3]和low[1]都变成了1。然后返回到1,1可继续搜,搜到2,2链接到之前的点,则low[2] = DFN[4]. 在返回到1,则此时形成一个scc( 1 3 4 2).

转载于:https://www.cnblogs.com/ac2012/archive/2011/02/27/1966577.html

强连通分量算法(2)相关推荐

  1. JavaScript实现strongly Connected Components 强连通分量算法(附完整源码)

    JavaScript实现strongly Connected Components 强连通分量算法(附完整源码) Comparator.js完整源代码 LinkedListNode.js完整源代码 L ...

  2. C++Kosaraju找有向图的强连通分量算法(附完整源码)

    C++Kosaraju找有向图的强连通分量算法 C++Kosaraju找有向图的强连通分量算法完整源码(定义,实现,main函数测试) C++Kosaraju找有向图的强连通分量算法完整源码(定义,实 ...

  3. 有向图的强连通分量算法

    有向图的强连通分量算法 强连通分量定义 在有向图中,某个子集中的顶点可以直接或者间接互相可达,那么这个子集就是此有向图的一个强连通分量,值得注意的是,一旦某个节点划分为特定的强连通分量后,此顶点不能在 ...

  4. 强连通分量算法学习笔记

    强连通分量 更好阅读体验请点击此链接 先推荐几道综合性较强的题目,详细题解我写了,持续更新中. 我的博客:整理 + 题解 P2341 [USACO03FALL][HAOI2006]受欢迎的牛 G P2 ...

  5. 算法提高课-图论-有向图的强连通分量-AcWing 1174. 受欢迎的牛:tarjan算法求强连通分量、tarjan算法板子、强连通图

    文章目录 题目解答 题目来源 题目解答 来源:acwing 分析: 强连通图:给定一张有向图.若对于图中任意两个结点x,y,既存在从x到y的路径,也存在从y到x的路径,则称该有向图是"强连通 ...

  6. 图之强连通、强连通图、强连通分量 Tarjan算法

    一.解释 在有向图G中,如果两个顶点间至少存在一条互相可达路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的极大强 ...

  7. Kosaraju算法(发现强连通分图算法)

    看论文的时候,看到Kosaraju算法.Kosaraju是一个强连通分图的发现算法,如有代码中有详细的注释,所以就不赘述了.直接上码(使用webgraph库实现,在我之前的文章中,对webgraph有 ...

  8. 【C++】强连通分量

    强连通分量 先来一题例题 题目大意 怎么做? 分析 结论 不要高兴得太早 怎么办呢? 定义 缩点法 原图构建新图 发现 新的结论 强连通分量算法 Kosaraju算法 Tarjan算法 例题:信息传递 ...

  9. Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)...

    转载自:http://hi.baidu.com/lydrainbowcat/blog/item/2194090a96bbed2db1351de8.html 基本概念: 1.割点:若删掉某点后,原连通图 ...

最新文章

  1. Flutter 网络请求库http
  2. Mysql高级调优篇——第三章:Sql实战调优场景剖析(上)
  3. jQuery一些常用特效方法使用实例
  4. 使 IDEA 的 termina l可以使用 Linux 下的终端命令
  5. 【unity】与Android Activity交互并调用JAVA代码传递参数
  6. html5 markdown,Markdown常用语法
  7. firewallD卸载Linux,在Ubuntu 18.04/16.04系统上安装和使用Firewalld的方法
  8. json 数据 生成 图表_比Excel更美观!你可知PhotoShop也能画图表
  9. mybatis输出SQL格式化
  10. ASCII码值转化十六进制,十进制数;十六进制字符值转十进制,ASCII码值;
  11. html5文字布局排版欣赏,用文字作为主体排版的15个网页设计案例
  12. mysql删不掉怎么办_mysql删除不彻底的解决方法_MySQL
  13. HTML页面嵌入视频无法播放的常见原因
  14. html电话号码隐藏样式,打电话不显示号码怎么设置(教你打电话隐藏号码)
  15. RPL协议的原理与安全机制
  16. EHub_tx1_tx2_E100 Cartographer 完美部署安装
  17. 数据结构:单链表中在P结点前插入S结点
  18. 自定义View基础之——canvas,paint的基本用法
  19. 【Vue学习笔记】尚硅谷Vue2.0+Vue3.0全套教程丨vue.js从入门到精通
  20. 运行node时报错:events.js:167 throw er; // Unhandled 'error' event

热门文章

  1. AngularJS JetBrains WebStorm简介
  2. swift 对象转换_Swift类型转换–照原样,任何对象
  3. Java新职篇:for循环
  4. centos下eclipse的安装
  5. mongodb维护常用命令
  6. 在OL6.5_64上安装Oracle11gR2_64
  7. mapreduce的二次排序 SecondarySort
  8. Webservice检查
  9. 供应商与客户 连接平台 的谋合
  10. [转摘]使用异步方式调用同步方法