我一直在研究关于它们的SCC和算法,我发现人们几乎总是提到Kosaraju的算法找到SCC并且还以(反向)拓扑排序对它们进行排序
我的问题是:Tarjan的算法还没有找到(反向)拓扑排序吗?我发现它没有被提及(至少从我读过的地方,除了维基百科)。
我一直在思考这个问题并且非常有意义。当在某个节点u上调用tarjans_dfs时,可以在u的SCC之前找到所有可从u访问的SCC。我错了吗?
维基百科说它确实找到了它:
"虽然其中的节点顺序没有什么特别之处 每个强连通组件,一个有用的属性 算法是不识别强连通分量 在任何继任者之前。因此,顺序在哪 识别出强烈连接的组件构成反向 拓扑排序由强连接形成的DAG 部件"
这是我的想法,还是更为人所知的是Kosaraju的算法找到了拓扑顺序而不是Tarjan的事实呢?
答案 0 :(得分:2)
是的,确实如此。 Tarjan的SCC算法通过在图上执行DFS并跟踪堆栈上SCC的根来工作。找到拓扑排序的一种方法是在图上执行DFS并跟踪退出顺序。 Tarjan的SCC算法中这些节点的退出顺序提供了拓扑排序。
在谈到Tarjan的SCC算法时,Donald Knuth甚至提到了in an interview,他说这是他最喜欢的算法之一:他为这个问题设计的数据结构以一种非常漂亮的方式组合在一起,因此在探索有向图时您需要查看的数量总是神奇地触手可及。他的算法也将拓扑排序作为副产品。
答案 1 :(得分:0)
是。由于Tarjan基于深度优先搜索所有你需要做的就是当每个顶点到达"关闭"时,将顶点添加到列表的顶部。 state。(即,它的dfs / tarjan调用以该顶点结束)
这是一个C / C ++ /伪代码示例:
void tarjan(int u) {
visited[u] = true;
closed[u] = false;
//dfs + tarjan processing
for (vi v = G[u].begin(); v != G[u].end(); v++) {
if (!visited[*v]) {
dfs(*v);
} else if (!closed[*v]) {
// has Cycle
}
}
closed[u] = true;
//add u to the top of your list here
}
答案 2 :(得分:-1)
确实如此,我一直在使用它,我想到了同样的问题。
我实际上没有时间来展示它,但每个测试用例(成千上万)总是会返回一个拓扑排序的压缩图。