tarjan模板及应用

tarjan的用处很多

对有向图:求强联通分量

对无向图:求割点、求桥。特别地,可以分离仙人掌图里的环

先贴一个看到不错的博客:点击打开链接

//有向图强联通分量
void  tarjan(int  x){
	dfn[x] = low[x] = ++times;
	S.push(x);f[x] = true;
	for  (int  i = head[x];i;i = nex[i])
		if  (!dfn[des[i]]){
			tarjan(des[i]);
			low[x] = min(low[x], low[des[i]]);
		}
		else  if  (f[des[i]])  low[x] = min(low[x], dfn[des[i]]);
	if  (dfn[x] == low[x]){//block in stack S
		nn++;
		int  y;
		do{
			y = S.top();S.pop();
			val[nn] ++;f[y] = false;blo[y] = nn;
		}while  (y != x)
	}
}

//无向图求割点或桥,注意割点的判断条件
void  tarjan(int  x,int  pre){
	dfn[x] = low[x] = ++times;
	int  child_cnt = 0;
	bool  flg = false;
	for  (int  i = head[x];i;i = nex[i]){
		int  y = des[i];
		if  (!dfn[y]){
			S.push(i);//edges in stack
			tarjan(y, i^1);
			low[x] = min(low[x], low[y]);
			if  (low[y] > dfn[x]){}//(x, y) is bridge
			if  (low[y] >= dfn[x]){//point x
				flg = true;
			   
			}
			child_cnt ++;
		}
		else  low[x] = min(low[x], dfn[y]);
	}
	if  (pre == 0 && child_cnt > 1)  cnt++;
	if  (pre && flg)  cnt++;
}

//仙人掌图(只有简单环,一条边最多出现在一个环里)求环,例:HDU6041
	dfn[x] = low[x] = ++times;
	for  (int  i = head[x];i;i = nex[i]){
		int  y = des[i];
		if  (!dfn[y]){
			S.push(i);
			dfs(y, i^1);
			low[x] = min(low[x], low[y]);
			if  (low[y] >= dfn[x]){
				int  j;
				T.resize(0);
				do{
					j = S.top();
					S.pop();
					T.PB(w[j]);
				}while  (j != i);
			}
		}
		else  if  (i != pre && dfn[y] < dfn[x])
			S.push(i), low[x] = min(low[x], dfn[y]);
	}
}

一些细节:1、如果栈内存边,应该top从2开始标号

                    2、割点的判断条件有两种:如果是根,只需要实边的儿子数大于一,否则需要有满足low[y]>=dfn[x]这个条件的实边儿子。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值