检查有向图是否强连接的算法

时间:2009-09-16 18:45:33

标签: algorithm directed-graph strongly-connected-graph

我需要检查有向图是否强连接,换句话说,是否所有节点都可以被任何其他节点(不一定是通过直接边缘)到达。

执行此操作的一种方法是在每个节点上运行DFS和BFS,并查看所有其他节点仍可访问。

有更好的方法吗?

8 个答案:

答案 0 :(得分:24)

考虑以下算法。


  1. 从图v的随机顶点G开始,然后运行DFS(G, v)

    • 如果DFS(G, v)无法覆盖图表G中的每个其他顶点,则会有一些顶点u,因此v没有定向路径到u,因此G 没有强烈关联

    • 如果它到达每个顶点,则会有v到图G中每个其他顶点的有向路径。

  2. 反转有向图G 中所有边的方向。

  3. DFS开始再次运行v

    • 如果DFS无法到达每个顶点,则会有一些顶点u,这样原始图形中就没有从uv的有向路径。

    • 另一方面,如果它确实到达每个顶点,那么在原始图形中,存在从每个顶点uv 的有向路径。

  4. 因此,如果G“通过”两个DFS,则它是强连接的。此外,由于DFS在O(n + m)时间运行,因此该算法在O(2(n + m)) = O(n + m)时间内运行,因为它需要2次DFS遍历。

答案 1 :(得分:14)

Tarjan's强连接组件算法(或Gabow's变体)当然就足够了;如果只有一个强连接组件,则图形连接很强。

两者都是线性时间。

与正常深度优先搜索一样,您可以跟踪每个节点的状态:新节点,已查看但仍处于打开状态(它位于调用堆栈中),并且已查看并已完成。此外,您可以在第一次到达节点时存储深度,以及从节点可以访问的最低深度(在完成节点后就知道了这一点)。如果最低可达深度等于其自身深度,则节点是强连接组件的根。即使您从根到达节点的深度不是最小可能的深度,这也可以工作。

要检查整个图是否是单个SCC,请从任何单个节点启动dfs,当您完成时,如果最低可达深度为0,并且每个节点都被访问过,那么整个图是强烈联系。

答案 2 :(得分:2)

要检查每个节点是否都具有给定图中每个其他节点的往返路径:

1。来自所有节点的DFS / BFS:

Tarjan's algorithm假定每个节点的深度为d[i]。最初,根的深度最小。然后,我们对d[i] = min(d[j])的任何邻居j进行后DFS更新i。实际上,BFS也可以在此处使用归约规则d[i] = min(d[j])

function dfs(i)
    d[i] = i
    mark i as visited
    for each neighbor j of i: 
        if j is not visited then dfs(j)
        d[i] = min(d[i], d[j])

如果存在从uv的转发路径,则为d[u] <= d[v]。因此,在SCC d[v] <= d[u] <= d[v]中,SCC中的所有节点将具有相同的深度。为了判断图是否为SCC,我们检查所有节点是否都具有相同的d[i]

2。来自单个节点的两个DFS / BFS:

它是Kosaraju’s algorithm的简化版本。从根开始,我们检查DFS / BFS是否可以访问每个节点。然后,反转每个边缘的方向。我们检查是否可以从同一根再次访问每个节点。参见C++ code

答案 3 :(得分:1)

您可以计算All-Pairs Shortest Path并查看是否有无限。

答案 4 :(得分:1)

已经提到了Tarjan的算法。但我经常发现Kosaraju's Algorithm更容易理解,即使它需要两次遍历图形。 IIRC,在CLRS中也很好地解释了它。

答案 5 :(得分:1)

test-connected(G)
{
    choose a vertex x
    make a list L of vertices reachable from x,
    and another list K of vertices to be explored.
    initially, L = K = x.

    while K is nonempty
    find and remove some vertex y in K
    for each edge (y, z)
    if (z is not in L)
    add z to both L and K

    if L has fewer than n items
    return disconnected
    else return connected
}

答案 6 :(得分:0)

这样做的一种方法是为图生成Laplacian matrix,然后计算特征值,最后计算零的数量。如果只存在一个零特征值,则图形是强连接。

注意:注意为有向图创建拉普拉斯矩阵的方法略有不同。

答案 7 :(得分:0)

您可以使用Kosaraju基于DFS的简单算法来执行两次DFS遍历图:

这个想法是,如果每个节点都可以从顶点v到达,并且每个节点都可以到达v,那么图形就是强连接的。 在算法的第2步中,我们检查是否可以从v到达所有顶点。在步骤4中,我们检查所有顶点是否都可以到达v(在反向图中,如果所有顶点都可以从v到达,那么所有顶点都可以达到v原始值图)。

算法: 1)将所有顶点初始化为未访问。

2)从任意顶点开始对图进行DFS遍历v。如果DFS遍历不访问所有顶点,则返回false。

3)反转所有弧线(或找到图形的转置或反转)

4)在反转图中将所有顶点标记为未访问。

5)从相同的顶点v开始执行反向图的DFS遍历(与步骤2相同)。如果DFS遍历不访问所有顶点,则返回false。否则返回true。

时间复杂度:如果使用邻接列表表示来表示图形,则上述实现的时间复杂度与深度优先搜索相同,即O(V + E)。