tarjan算法求强连通分量

本来我是打算去网上看Tarjan求LCA的。。结果发现了一篇挺好的介绍tarjan算法求强连通分量的文章。

首先理解什么是强连通分量,简单来说,可以相互连通的区域成为强连通分量;若是u能到达v且v能到达u,且u,v与其它结点不能相互连通,则{u,v}是一个强连通分量。

谈谈我对tarjan的理解,图解过程详见:http://www.cnblogs.com/shadowland/p/5872257.html,解释得真的很好。

tarjan基于深搜,首先定义一个栈用于存储结点,在深搜的过程中,结点进栈,DFN[i]表示第i结点是第几个被遍历的(或者说是第几个进栈的);

LOW[i]表示第i结点及i所在的子树可追溯到的最早进栈的结点的进栈次序,若拓展结点时找到了在栈中的结点,则更新LOW取较小的值;

回溯时,若DFN[i]==LOW[i],则i结点到栈顶结点所有结点为同一强连通分量。

详见代码:

void tarjan(int now) //用链式前向星存图实现的tarjan
{
	dfn[now]=++t;
	low[now]=t;
	flag[now]=true; //flag表示是否被访问过
	stack[++top]=now;
	int k=top; 
	int u=head[now];
	while (u!=0)
	{
		if (!flag[edge[u].to]) tarjan(edge[u].to);
		if (!del[edge[u].to]) low[now]=min(low[now],low[edge[u].to]); //del表示是否在栈中,为false,说明edge[u].to未被归到强连通分量里,那么这两个点必定互相连通(可画图证明) 
		u=edge[u].next;
	}
	if (dfn[now]==low[now]) //满足该条件,则当前点一直到栈顶点已经构成一个强连通分量 
	{
		for (int i=k;i<=top;i++) del[i]=true; //出栈
		if (top-k+1>ans) //此程序为取最大结点数最小字典序的强连通分量
		{
			ans=top-k+1;
			for (int i=k;i<=top;i++) que[i-k+1]=stack[i];
			sort(que+1,que+top-k+1+1,cmp); //stl库排序,终止点为数列长度+1 
		} 
		else if (top-k+1==ans)
		{
			for (int i=k;i<=top;i++) comparison[i-k+1]=stack[i];
			sort(comparison+1,comparison+top-k+1+1,cmp);
			if (comparison[1]<que[1])
				for (int i=1;i<=ans;i++)
					que[i]=comparison[i];
		}
		top=k-1; //出栈
	} 
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值