查找有向图的每个弱连通分量的算法

Posted

技术标签:

【中文标题】查找有向图的每个弱连通分量的算法【英文标题】:Algorithm for finding every weakly connected component of a directed graph 【发布时间】:2016-03-18 18:17:14 【问题描述】:

我正在寻找一种算法来查找有向图中的每个弱连通分量。我知道对于无向图,您可以通过 dfs 执行此操作,但这显然不适用于有向图。我将我的图表保存为相邻列表。 例如:

A -> B
B -> C
D -> X

所以 A-B-C 是 D-X 的连通分量

我不是在寻找寻找强连通分量的算法!!

【问题讨论】:

嗯,你应该准确地说你的意思是你在谈论有向图中的连通分量。您是指以“无向方式”连接的组件吗? 据我所知,有向图没有连通分量,您可以讨论弱连通分量(为此您只需使用 dfs + 将图转为无向)和强连通分量。你能更好地定义有向图的连通分量是什么意思吗? 好的,只要把所有的边都变成无向的,然后找到组件 您所说的“已连接”是什么意思。有向图中不存在“连接的组件”。只有“强连通分量”和“弱连通分量”。在目前的状态下,这个问题应该被关闭为“不清楚你在问什么”。 【参考方案1】:

除非您的内存限制太严格,否则您可以保留第二个临时邻接列表。在第二个邻接列表中,您将每条边 a->b 放在一边,并且还将边放在相反的方向上。 (即 b->a)然后,您可以在该邻接列表上使用 DFS 来查找连接的组件。

【讨论】:

实际上应该将反向存储到每个边缘,从而减少所需的空间。 我认为将有向图概念化为无向图会更容易。毕竟空间复杂度是一样的。不过,您显然是正确的。它将所需空间减半,不存储原始图的边缘两次。【参考方案2】:

一个非常简单的解决方案如下: 首先从给定的图创建一个无向图 - 只需制作一个副本并将每条边的反向添加到边集。创建顶点集的副本,从任意顶点开始,然后 DFS 遍历包含该顶点的组件,从集合中删除所有遍历的节点并将它们添加到列表中。重复此操作,直到列表为空。

在伪代码中:

bimap edges
edges.putAll(graph.edges())

set vertices = graph.vertices()

list result

while !vertices.isEmpty()
    list component

    vertex a = vertices.removeAny()
    dfsTraverse(a , v -> 
        vertices.remove(v)
        component.add(v)
    )

    result.add(component)

【讨论】:

以上是关于查找有向图的每个弱连通分量的算法的主要内容,如果未能解决你的问题,请参考以下文章

算法笔记_144:有向图强连通分量的Tarjan算法(Java)

强连通分量

强连通分量的Tarjan算法

有向图强连通分量的Tarjan算法

图的连通性算法

Tarjan算法强连通分量