我正在阅读有关BFS和DFS的图算法。当我分析通过DFS在Graph中查找强连通分量的算法时,我想到了一个疑问。为了找到强连通组件,哪本书(Coremen)做了,首先它在图表上运行DFS以获得顶点的结束时间然后再次按照完成时间的降序在图表的转置上运行DFS我们从第一个DFS得到的。但是我无法理解为什么第二个DFS必须按照完成时间运行。 我的意思是即使我们直接在图的转置上运行DFS(忽略完成时间),它是否也给了我们连接的组件,因为通过转置我们已经阻止了到其他组件的路径。
答案 0 :(得分:15)
编辑 - 这是斯坦福大学关于这个主题的一些很好的深入视频:
http://openclassroom.stanford.edu/MainFolder/CoursePage.php?course=IntroToAlgorithms(参见6.直接图中的连通性)
我的解释:
如果您没有根据第一个dfs的减少完成时间运行第二个dfs,则可能会错误地将整个图表识别为单个强连接组件(SCC)。
请注意,在我的示例中,节点d
始终具有与第一个dfs相比最短的完成时间。节点a
,b
或c
之一将具有最高的完成时间。假设a
具有最高的完成时间,因此如果我们根据减少的完成时间运行第二个dfs,a
将是第一个。
现在,如果您在d
的转置中以节点G
开始运行第二个dfs,您将生成包含整个图形的深度优先林,因此得出结论:整个图形是一个SCC,显然是假的。但是,如果您使用a
启动dfs,那么您不仅会发现a
,b
和c
作为SCC,而且重要的部分是它们将被标记为已访问,颜色为灰色或黑色。然后,当您继续d
上的dfs时,您将不会遍历其SCC,因为您会意识到其相邻节点已被访问过。
如果你看看DFS的cormens代码,
DFS(G)
1 for each vertex u in G.V
2 u.color = WHITE
3 u.π = NIL
4 time = 0
5 for each vertex u in G.V
6 if u.color == WHITE
7 DFS-VISIT(G, u)
DFS-VISIT(G, u)
1 time = time + 1 // white vertex u has just been discovered
2 u.d = time
3 u.color = GRAY
4 for each v in G.adj[u]
5 if v.color == WHITE
6 v.π = u
7 DFS-VISIT(G, u)
8 u.color = BLACK // blacken u; it is finished
9 time = time + 1
10 u.f = time
如果你没有使用减少完成时间,那么DFS的第6行只会是真一次,因为DFS-VISIT会递归地访问整个图。这会在深度第一个林中生成一个树,每个树都是一个SCC。单个树的推理是因为树的根节点具有零前导码。