这个问题与最近在这里提出的问题相关但不同。
我刚刚阅读了Wikipedia 伪代码。
algorithm tarjan is
input: graph G = (V, E)
output: set of strongly connected components (sets of vertices)
index := 0
S := empty
for each v in V do
if (v.index is undefined) then
strongconnect(v)
end if
end for
function strongconnect(v)
// Set the depth index for v to the smallest unused index
v.index := index
v.lowlink := index
index := index + 1
S.push(v)
// Consider successors of v
for each (v, w) in E do
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
end for
// If v is a root node, pop the stack and generate an SCC
if (v.lowlink = v.index) then
start a new strongly connected component
repeat
w := S.pop()
add w to current strongly connected component
until (w = v)
output the current strongly connected component
end if
end function
我显然不能正确理解它,因为我有两个非常基本的问题:
当我们说 时
if (w is in S)
,这不是 O(N) 或至少 O(logN) 复杂度的操作,因为元素应按其索引排序吗?我们必须为从根节点访问的每个新节点执行此操作,因此总体复杂性不是O(NlogN)
。此外,S 是一个堆栈,所以从概念上讲,只有顶部元素应该是可访问的,我们如何在其中实现搜索?在这里,二叉搜索树不应该是更好的数据结构吗?在这部分:
else if (w is in S) then
v.lowlink := min(v.lowlink, w.index)
w.index
使用和不使用是否有特定原因w.lowlink
?使用的好处w.lowlink
是它可以回答上一个问题(链接问题)。对于LLs
SCC 中的所有节点,将保证所有节点都相同。