不完全浅析Tarjan求强连通分量(SCC)

本文介绍了一种使用Tarjan算法寻找图中的强连通分量的方法。通过深度优先搜索(DFS)来标记每个节点的时间戳和可达最浅祖先,进而找到所有强连通子图。

定义dfn[]为每个点的时间戳(搜索次序),low[]为每个点的所能追溯到的,最低dfn的祖先的dfn,也就是最浅祖先
证明我真的不会,只能自己YY,不确保说的每句话都是正确的,如果我的分析有错误请一定要指出来!!!
先走dfs。一个有SCC的图一定有环,所以当搜索到一个已经到过的点时,我们就找到了一个环,此时这个环上所有的点一定都强联通(就好比地球是圆的,所以一直沿某个方向是可以回到起点的),这个环就是一个强联通子图,我们最后找的就是一个极大的环。
用栈保存读入的点,每遇到一个dfn==low的点,就说明找到了这个环的祖先,将这个祖先以及后于其加入栈的点弹出来,并且标记flag[弹出的点]=false,
flag用来确保把某个环剔出去,这样在求其他的环时就不会因为环上某条指向应该被删除的某个环的单向边而被影响。

void tarjan(int x) {
	dfn[x] = low[x] = ++count;
	s[++top] = x;
	flag[x] = 1;
	for(int i=last[x]; i; i=e[i].next){
		int v = e[i].to;
			if(!dfn[v]) {
				tarjan(v);
				if(low[x] > low[v]) 
					low[x] = low[v];
			}
			else if(dfn[v] < low[x] && flag[v]) 
				low[x] = dfn[v];
			
	}
	if(dfn[x] == low[x]) {
		int j, k = 0;
		sccnum++;
		do{
			j = s[top--];
			flag[j] = 0;
			k++;
		}while(j!=x);
	}
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值