我正在阅读Tarjan's algorithm的描述,以便在干扰图中找到强关联组件。 但我发现很难理解这些代码片段:
if (w.index is undefined) then
// Successor w has not yet been visited; recurse on it
strongconnect(w)
v.lowlink := min(v.lowlink, w.lowlink)
else if (w is in S) then
// Successor w is in stack S and hence in the current SCC
v.lowlink := min(v.lowlink, w.index)
end if
第四行和第七行不同,这让我很困惑。
在我看来,第四行可以用与第四行相同的方式编写
v.lowkink := min(v.lowlink, w.index)
我在我的程序中对此进行了测试,并且工作正常,对我来说,了解bcz verdex v cloud达到了根本的效果更好,但我无法证明它是T_T。
答案 0 :(得分:0)
我编写了一个程序,它枚举了所有大小为4的图形,然后运行每个版本(如果w在S中,则使用min(v.lowlink, w.index)
或min(v.lowlink, w.lowlink)
)并比较结果。两者在所有情况下完全相同,即使w.lowlink和w.index通常不同。
我们可以使用w.index的原因是:考虑堆栈S相对于当前节点v的位置v是另一个节点w。
如果它早于堆栈,那么它的索引比当前节点小(因为它之前被访问过,duh),所以当前节点不是其连接组件的“头”,这将反映在v中.lowlink< = w.index< v.index无论如何。并且它不像w.lowlink在这一点上具有任何特定含义,它在计算的过程中并且不一定具有其最终值。
现在,如果w在堆栈中比v更晚,那么算法所依赖的关键属性是w然后是v的后代,而不是某些兄弟/ cousing节点仍然从早期的递归调用中留下。或者,正如通常在完整证明中所述,强连接组件从不跨越我们的搜索树(林)的几个未连接的分支。因为它是一个SCC,所以必须有一条从w到v的路径,因为我们按深度优先顺序枚举东西,所以我们必须在完成处理w之前使用w的路径访问v,所以w应该是堆栈中早于v!
如果w是v的后代,那么我们第一次访问它时已经得到了它的实际低链接值,并且不再对它感兴趣了。
另一方面,摆脱节点上的lowlink属性并使strongconnect直接返回它是微不足道的。然后我们不想在第二种情况下检查它而不是w.index =)