我在一个家庭作业问题上遇到了一些麻烦,涉及在提供的图表上使用 Tarjan 算法来找到该图表的特定 SCC。虽然(根据我的教授)我通过使用此处找到的伪代码算法找到了正确的 SCC ,但我的 SCC 中的一些节点与该 SCC 的根节点不共享相同的最低链接号。
从我可以从伪代码中收集到的信息来看,这是因为如果一个未引用的节点i
(它是当前递归调用算法的输入节点)与一个已经访问过的节点(不是根节点)有i + 1
一条弧线,然后算法设置i
s LL = MIN(i.LowestLink, (i + 1).index)
,并且(i + 1).index
可能不再等于它自己的最低链接值。
例如(这类似于我要解决的问题中的图的一部分):如果我们在 中有节点,在 中有N = {a, b, c, d}
弧E = {a ⇒ c, c ⇒ b, c ⇒ d, b ⇒ a, d ⇒ b}
,并且我们从中启动算法的根节点是a
,那么:
1.1) 我们设置a.index = 1
(使用 1 而不是 0), a.LL = 1
, 并压入a
堆栈;a
有一个单一的弧线c
,所以我们检查c
; 发现它未被发现,我们将算法称为c
.
2.1) 我们设置c.index = 2
, c.LL = 2
, 并c
入栈;c
有两条弧线,一条到b
,一条到d
。假设我们的 for 循环b
首先检查;b
未被发现,因此我们将算法称为b
。
3.1) 我们设置b.index = 3
, b.LL = 3
, 并压入b
堆栈;b
有一个弧到a
; 检查a
我们发现它已经在堆栈上,所以(通过上面链接的伪代码)我们设置b.LL = MIN(b.LL, a.index) = a.index = 1
; b
没有更多的弧,所以我们退出我们的 for 循环,并检查 if b.LL = b.index
,它没有,所以我们结束这个算法的实例。
2.2) 现在递归调用b
已经结束,我们设置c.LL = MIN(c.LL, b.LL) = b.LL = 1
. c
仍有从c
到d
剩余的弧;检查d
我们发现它是未定义的,所以我们调用算法 on d
。
4.1)d.index
设置为 4,d.LL
设置为 4,然后我们压入d
堆栈。从到d
有一条弧,所以我们检查; 我们发现它已经在堆栈中,所以我们设置. 没有更多的弧线,所以我们退出我们的 for 循环并检查 if ; 它没有,所以我们结束这个算法的实例。d
b
b
b
d.LL = MIN(d.LL, b.index) = b.index = 3
d
d.LL = d.index
2.3) 随着递归调用d
结束,我们再次设置c.LL = MIN(c.LL, d.LL) = c.LL = 1
. c
没有更多的弧,所以我们结束了我们的 for 循环。我们检查是否c.LL = c.index
;它没有,所以我们结束这个算法的实例。
1.2) 随着递归调用c
结束,我们设置a.LL = MIN(a.LL, c.LL) = 1
. a
没有更多的弧线,所以我们结束了我们的 for 循环。我们检查是否a.LL = a.index
;它们是相等的,所以我们找到了这个 SCC 的根节点;我们创建一个新的 SCC,并将堆栈中的每个项目弹出到这个 SCC 中,直到我们a
在堆栈中找到(也进入这个 SCC)。
在这些步骤之后,图中的所有节点都被发现了,因此与其他节点一起运行算法最初什么都不做,我们有一个SCC = {a, b, c, d}
. 但是,d.LL = 3
这不等于其余节点的最低链接(全为 1)。
我在这里做错了吗?或者在这种情况下是否有可能在其节点之间拥有一个具有不同最低链接的 SCC?