编程语言
首页 > 编程语言> > 强连通分量(Tarjan算法) 图解

强连通分量(Tarjan算法) 图解

作者:互联网

强连通分量(Tarjan算法)

在这里插入图片描述

如图,从点1开始深搜,给搜过的点打上时间戳dfn,初始化low,stack = 1 3 2

在这里插入图片描述

当搜到点2时,下一个搜到了1,1已经被搜过了(已经被搜过了看 dfn[] != 0 ),且1在栈内
修改 low[2] = min(low[2], dfn[1]); (注意绕回根节点的时候是将该点的low和根节点的dfn比较)

在这里插入图片描述

此时点2搜完了,回溯到点3. 点3是回溯来的修改low肯定是和点2的low比较
即修改 low[3] = min(low[2], low[3]);

在这里插入图片描述

点3继续深搜,给4,5打上时间戳,同时入栈4,5,此时栈内有 stack = 1 3 2 4 5

在这里插入图片描述

5继续搜,搜到4,点4已经搜过且在栈内,修改low[5] = min(low[5], dfn[4])
回溯到点4,点4修改low[4] = min(low[4], low[5])

在这里插入图片描述

下一步是关键,此时点4已经搜完,即将退出回溯到点3,而我们发现点4的dfn[4] == low[4]
也就是说点4就是一块强连通分量的节点!
此时开始出栈,直到点4出栈为止。即剩下的stack = 1 3 2
我们给出栈的点全部打上scc标记,即

在这里插入图片描述

待出栈结束,回溯到点3
点3此时修改low[3] = min(low[3], low[4]), 显然low3不变
继续回溯到点1,发现点1已经搜完,且dfn[1] == low[1]
同上述点4,出栈打标记

在这里插入图片描述

此时栈已经空了,从1开始深搜已经结束,但很明显还有一个6没有被搜过
可以很明显看出上述算法不一定能走遍整个图,所以需要以每一个点为起点深搜一次,判断标准是是否被搜过(即dfn[] != 0)

for(int i = 1; i <= n; i++){
	if(!dfn[i]) tarjan(i);
}

在坚持一下,马上就要结束了
此时其实还有最后问题没有解决,就是那个栈有什么用,让我们继续深搜点6
dfn[6] = 6, low[6] = 6,下一个要搜的点是2
2已经被搜过,但是和上面都不一样的地方来了!2此时不在栈里
所以我们不用更新low[6],直接结束搜点6.

最后,low[6] == dfn[6], 打上scc标记,整个算法就讲完了。

在这里插入图片描述

标签:Tarjan,int,连通,edge,++,dfn,low,cnt,图解
来源: https://blog.csdn.net/qq_25930891/article/details/123208901