【发布时间】:2015-09-01 13:16:56
【问题描述】:
我正在学习 Kosaraju 算法,用于从这里 Kosaraju algorithm 查找强连通分量。
但是我不明白按照完成时间的递减顺序执行 dfs(G^T) 的必要性是什么,即上面链接中的第 3 点中提到的。
【问题讨论】:
-
如有任何疑问,请随时咨询。
我正在学习 Kosaraju 算法,用于从这里 Kosaraju algorithm 查找强连通分量。
但是我不明白按照完成时间的递减顺序执行 dfs(G^T) 的必要性是什么,即上面链接中的第 3 点中提到的。
【问题讨论】:
考虑一个简单的图,它有两个顶点 A 和 B,一条边从 B 到 A(或 G^T 中的 A 到 B)。如果您按照 A 然后 B 的顺序对顶点执行 dfs(G^T) ,那么您将其输出为单个强连通分量。而它应该是两个独立的组件。
非正式地,按指定顺序做顶点的必要性是确保你只有在你也可以先“向下” G 链接时才“向上” G^T 链接。
【讨论】:
画一个只是路径的图。
5 -> 4 -> 3 -> 2 -> 1
如果我们不按完成时间的递减顺序对转置进行 DFS,那么我们可以从例如 4 开始,并将 {4, 5} 报告为一个组件。
【讨论】:
假设你的原始图表是这样的:
C1、C2、C3 和 C4 是图的强连通分量,可以包含任意数量的顶点。
如果我们的目标是找到图中的强连通分量,最好的办法是从 C4 的任何顶点开始 DFS 并标记它们已访问。
原因:因为C4是一个SCC,并且没有来自C4的出边,从C4的任意一个顶点发起DFS只会访问C4的顶点为没有传出顶点。
所以我们得到了第一个 SCC。
下一步将从C2或C3的顶点开始DFS,因为C2(OR c3)是SCC,它将访问C2(OR c3)的所有顶点并且唯一的出边是C4 WHOSE顶点已标记为已访问,因此不会包含在 SCC 中。
所以我们得到了第二个 SCC。
下一步是从 C2(如果之前是 C3)启动 DFS,否则从 C3(如果之前是 C2)。并且它最终只会访问那个 SCC 的顶点,原因已经在上面提到了。
最后,我们将从 C1 的一个顶点开始 DFS,它会结束仅访问该 SCC(C1) 的顶点,原因在上面已经提到。
现在我将回答您的问题
C4,C3,C2,C1或C4,C2,C3,C1的顺序,基本上是作为顶点在完成时间递减的顺序得到的对于下图(原图反转)
也就是说,如果我们从上图的任何顶点开始 DFS,那么我们获得的按完成时间递减顺序的顶点列表将具有 首先是 C4 的顶点,然后是 C2 的顶点,然后是 C3 的顶点和最后是 C1 的顶点或 C4 的顶点,然后是 C3 的顶点,然后是 C2 的顶点,最后是 C1 的顶点。
如果我们不按完成时间的递减顺序启动 DFS,假设我们从 C1 的任何顶点(即在原始图的第二个 DFS 中)启动 DFS,那么 DFS 会做什么,它会列出图的所有顶点都作为一个 SCC,第一张图清楚地表明了这一点,因为从 C1 到 C2、C3 有出边,从那里我们可以到达 C4:
C2、C3、C4 的顶点标记为未访问
或者说,如果我们在从 C4 的任何顶点开始 DFS 之前从 C2 的任何顶点开始 DFS,它会做的是将 C2 和 C4 的顶点列为一个 SCC,因为 C4 顶点被标记为未访问。。
因此,按完成时间递减顺序启动第二个 dfs 的主要原因是,只有该 SCC 的顶点在 dfs 中列出并标记为已访问。
【讨论】: