我在使用提供的图表上使用Tarjan算法来找到该图的特定SCC时,会遇到一些问题。虽然(据我的教授说)我通过使用找到here的伪代码算法找到了正确的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循环,并检查b.LL = b.index
是否,但不是,所以我们结束了算法的这个实例。
2.2)现在b
上的递归调用已经结束,我们设置了c.LL = MIN(c.LL, b.LL) = b.LL = 1
。 c
仍然保留从c
到d
的弧线;检查d
我们发现它未定义,因此我们在d
上调用算法。
4.1)d.index
设置为4,d.LL
设置为4,我们将d
推送到堆栈。 d
有一个从d
到b
的弧,所以我们检查b
;我们发现b
已经在堆栈中,因此我们设置d.LL = MIN(d.LL, b.index) = b.index = 3
。 d
没有其他弧,所以我们退出for循环并检查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?