如何输出无向图的所有双连通分量?

时间:2014-02-12 16:08:56

标签: algorithm data-structures graph-theory depth-first-search

给定一般的无向图,我们如何在O(N + M)时间内打印图的所有双连通分量?我知道Tarjan的算法用于输出无向图的所有关节点,但我发现很难扩展算法来打印双连通组件。我尝试搜索谷歌,但我得到的所有结果都不适用于我的测试用例,因为他们错过了算法的边缘情况。

有人可以提供此问题的工作代码。

Def:双连通组件是一个连接的子图,不包含顶点,删除会断开子图。

编辑:我已成功实施了Niklas提供的this link中所述的算法。现在我有一个不同的问题,我怎样才能找到一个无向图的子图,其中没有边删除会断开子图。请帮我解决这个替代问题。

2 个答案:

答案 0 :(得分:6)

这是一个classical problem with a known linear-time algorithm。但是,您可能需要先将图形分解为连接的组件。来自维基百科的算法描述:

  

用于计算双连通组件的经典顺序算法   在约翰霍普克罗夫特和罗伯特的连通无向图中   Tarjan(1973)[1]以线性时间运行,并且基于深度优先   搜索。该算法也概述为引言的问题22-2   算法(第2版和第3版)。这个想法是运行一个   深度优先搜索,同时保留以下信息:   深度优先搜索树中每个顶点的深度(一旦获得)   访问),并为每个顶点v,所有的邻居的最低深度   深度优先搜索树中v的后代,称为   该lowpoint。深度是在深度优先期间保持的标准   搜索。访问所有后,可以计算v的低点   v的后代(即,在v弹出之前)   深度优先搜索堆栈)作为深度v的最小值,深度   v的所有邻居(除了v的父亲之外)   深度优先搜索树)和所有v的孩子的低点   深度优先搜索树。关键的事实是非根顶点v是a   切割顶点(或铰接点)分开两个双连体   组件当且仅当存在v的子y时   低点(y)≥深度(v)。这个属性可以测试一次   从v的每个孩子返回的深度优先搜索(即,只是   在v从深度优先搜索堆栈中弹出之前,如果   true,v将图形分成不同的双连通组件。   这可以通过计算一个双连通组件来表示   每个这样的y(包含y的组件将包含子树   y,加上v),然后从树中删除y的子树   根顶点必须单独处理:它只是一个切割顶点   如果它至少有两个孩子。因此,只需构建一个就足够了   根的每个子树的子组件(包括根)。

可以在http://www.cs.umd.edu/class/fall2005/cmsc451/biconcomps.pdf找到一个好的伪代码实现。

答案 1 :(得分:3)

Planarity Testing by Path Addition上查看这篇博士论文。

Chapter 5给出DFS算法的伪代码(使用递归或迭代的两个版本)和用于将DFS树(也称为Tremaux树)分区(分解)为路径段层次结构的算法(或链)。 Chapter 4根据路径段尾部在DFS树中的相对位置(相对于路径段的头部),将这些路径段分为4种不同的类型。

鉴于这种分离,您可以将树分区为双连通组件,以便:

  • 第1类路径段不是任何双连通组件的一部分;
  • 第2类(减去在段头部后面和尾部之前的边缘和顶点,类似于第1类段,不是任何双连通组件的一部分),第3类路径段形成一个循环并且位于开头(根)一个双连通组件;和
  • 第4类段是双连通组件的一部分,其中包含最近的2级或3级祖先路径段。

如果操作正确,您应该能够在O(V + E)时间内提取这些双连通组件。

论文后面有Java源代码,它在O(V + E)时间和时间进行全面平面度测试。内存可能会给你一些进一步的指针(并提取O(P(V + E))中双连通分量嵌入的所有排列P。)