强连通分量:Kosaraju 算法

Strongly Connected Components : Kosaraju algorithm

在 Kosaraju 算法中,我遇到了两种可能的实现:

1) 按原图中顶点的拓扑顺序在反转图中搜索强连通分量

2) 在反转图中按照顶点的拓扑顺序搜索原图中的强连通分量

我想知道,使用颠倒的拓扑顺序的顶点在原始图中搜索强连通分量是错误的。这在内存方面也会更好,因为不需要新的邻接列表。

来源 :1) E-Maxx , 2) CLRS 书籍

术语问题:

你说的是拓扑排序,但当且仅当图是 DAG(有向无环)时,拓扑顺序才存在。如果您只想使用 DAG,那么您已经拥有 SCC(强连通组件),因为每个顶点都是其自身的组件。如果您想在有向图上找到 SCC,则需要将 拓扑排序 更改为 DFS 完成时间 。 CLRS 书仅提到完成时间 f[u]:

  1. Call DFS(G^T), but in the main loop of DFS, consider the vertices in order of decreasing f[u]...

重新表述您的问题:

Is it wrong to search for strongly connected components in the original graph consider vertices in order of increasing finishing times f[u]?

答案:

对,错了

反例:考虑下图:

其中包含两个组件 CC'。如果您 运行 第一个 DFS(从节点 u 开始),您将按完成时间以升序结束以下两个列表之一:

DFS 列表 1:{v,w',w,u}

DFS 列表 2:{w',v,w,u}

你实际上问的是你是否可以在原始图上从头开始处理这些列表。如果您选择第一个列表,您将通过从节点 v 开始的 DFS 搜索提取组件 C',然后从节点 w' 开始通过 DFS 搜索提取组件 C。但是,如果您选择第二个列表并从原始图上的节点 w' 开始 DFS,您将只会得到一个组件(整个图),这是错误的。

请注意,Kosaraju 的算法在这两种情况下都有效,因为它从列表的末尾开始(在这两种情况下都是节点 u),并通过 DFS 搜索在反转图上提取组件 C。当我们到达列表中的节点 v 时,稍后将提取组件 C'

Kosaraju 算法 是一种线性时间算法,用于查找适用于有向图和无向图的强连通分量。为了更容易理解,我们可以在图中说如果任何一组节点构成一个循环是 强连通分量 (SCC)。 如果我们谈论蛮力方法来解决这个问题,我们可以按照以下步骤操作:

  1. 找到所有对最短路径使用 Floyd Warshall 算法.
  2. 检查任意两对之间的距离是否为无穷大,即无法到达则它不是 SCC 否则它是 SCC.

如果我们谈论这种方法的复杂性,它将花费立方时间,即 O(v^3)。因此,我们可以使用 Kosaraju 算法 优化此方法,该算法可以 运行 我们的算法在 O(n+m) 时间内完成。使用Kosaraju算法解决强连通分量问题的步骤是:

  1. 对图执行深度优先搜索(DFS)并将节点推送到堆栈。
  2. 通过反转图的边找到图的转置。
  3. 从堆栈中一个接一个地弹出节点,然后在修改后的图上再次执行 DFS

每个成功的 DFS 将五个 1-SCC 强连接 component.This Kosaraju 算法 在 [=16= 中的工作原理]O(n+m) 时间,其中 n 是图中的节点数,m 是边数。