连通分量(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];

	}

}

 

你可能感兴趣的:(tar)