连通分量(tarjan算法)

对于有向图中,连通分量叫强连通分量

对于无向图中,连通分量叫双连通分量,而在双连通分量中,又分为点双连通和边双连通。

重点讨论双连通的情况:

以割点区分连通情况的双连通叫做点双连通分量,以割边区分连通情况的双连通叫做边双连通分量。

比如这个图中:

1           4

| \       /   \ 

|   \   /       \

|     2          5

|   /   \       /

| /       \   /

3          6

如果要的到两个连通分量的话,我们只有以2节点为割点,将图分为点双连通。我们便可以得到两个双连通分量(1,2,3)、(2,4,5,6)。

再比如这个图:

1                5

| \             /   \ 

|   \         /       \

|     2 — 4       6

|   /         \       /

| /             \   /

3                7

如果要得到两个连通分量的话,我们只能以(2,4)边为割边,得到两个边双连通分量。

具体是将一个无向图分成点双连通还是边双连通得看具体的问题。下面具体讨论一下用tarjan算法实现起来的区别。

1、对于边双连通分量,由于是以边为连通间的区分,那么每个点只属于一个连通分量,我们在深度遍历的时候,只需要记录某一点是否被访问即可。

2、但是对于点双连通分量,由上图也可以看出,2节点同时属于两个连通分量,如果还是以节点为重判对象的话,将得到错误的答案。此时,我们应该以边为重判对象,而该边的两个端点,都同属于一个点双连通。

对于边双连通的实现,由于没有节点会重复属于两个以上的连通分量,所以我们可以先简单的遍历一遍整个图的tarjan标号(low、dnf)。之后再进行一次深度遍历,以low[v]>dnf[u]为换色标准染色,最后每种颜色即一个分量。

代码:

void tarjan(int u,int f) //f为父节点
{
	low[u]=dnf[u]=++count;
	visit[u]=1;
	S.push(u);
	for(node *p=link[u];p;p=p->next)
	{
		if(p->v==f)
			continue;
		if(!visit[p->v]) //一节点为重判对象
		{
			tarjan(p->v,u);
			if(low[u]>low[p->v])
			{
				low[u]=low[p->v];
			}
		}
		else if(low[u]>dnf[p->v])
			low[u]=dnf[p->v];
	}
}

void set_color(int u)
{
	for(node *p=link[u];p;p=p->next)
	{
		if(!color[p->v])
		{
			if(low[p->v]>dnf[u]) //找到了关键割边,换一种颜色染色
				color[p->v]=++cut;
			else
				color[p->v]=color[u]; //保持原来的颜色
			set_color(p->v);
		}
	}
}

对于点双连通的实现,经过上面的分析,由于存在点既属于A分量又属于B分量,所有我们此时采纳边为重判对象,而该边的两端点同属于一个分量

代码:

void col(int u)
{
	int x;node *p;
             ++cut;  
	do
	{
		p=stack[--top];
		color[p->v]=color[p->op->v]=cut;
	}while(p->op->v!=u);
}

void tarjan(int u)
{
	low[u]=dnf[u]=++cut;
	for(node *p=link[u];p;p=p->next)
	{
		if(p->vist) //该边已被访问
			continue;
		p->vist=p->op->vist=1;  //两个方向都标记已访问
		stack[top++]=p;   //该边进栈
		if(!dnf[p->v])
		{
			tarjan(p->v);
			if(low[u]>low[p->v])
				low[u]=low[p->v];
			if(low[p->v]>=dnf[u]) //找到了关键割点
				col(u);
		}
		else if(low[u]>dnf[p->v])
			low[u]=dnf[p->v];
	}
}
 
原文地址:https://www.cnblogs.com/ka200812/p/2126108.html