现在的位置: 首页 > 综合 > 正文

无向图和有向图关于连通性的tarjan算法

2019年09月22日 ⁄ 综合 ⁄ 共 1090字 ⁄ 字号 评论关闭

无向图的割顶,桥和构造双连通分量以及有向图的极大连通分量,相关概念看这里 http://www.byvoid.com/blog/biconnect/

程序部分自己写,理论部分参考上方链接。

根据黑书上面的相关内容,无向图的tarjan算法大致如下:

/*
 * 注释1:去除注释1即为无向图求割顶的算法。
 * 		  特别的,若最终 sons>1,则节点1也为一个割点。
 * 		  调用时 tarjan(1,0);
 * 注释2:去除注释2即为无向图求桥的算法。
 * 		  bridge[i]为真表示边的邻接表中的第i条边为桥。
 * 		  调用时 tarjan(1,0);
 * low[]的编号即为连通分量的编号。
 * */
void tarjan(int x,int father)
{
	int i,j;
	dfn[x] = low[x] = ++index;
	for(i=head[x];i;i=edge[i].next)
	{
		j = edge[i].v;
		if(j!=father)	//这个判断不要忽略了,特别在无向图中很重要。
		{
			if(!dfn[j])
			{
		//1		if(x==1) sons++;
				tarjan(j,x);
				low[x] = min(low[x],low[j]);
		//1		if(x!=1 && low[j]>=dfn[x]) cut[x] = true;
		//2		if(low[j]>dfn[x]) bridge[i] = true;
			}else
				low[x] = min(low[x],dfn[j]);
		}
	}
	return;
}

若要求构造双连通分量,则要利用LCA算法,还是Tarjan的成果。参见上方链接。

有向图的tarjan算法,求极大连通分量

/*
 * 有向图的tarjan算法,求极大连通分量。
 * 与无向图相比,去掉 j!=father 的判断。
 * 另外,low[]的编号不能表示连通分量的编号,
 *     而必须用栈来对结点进行编号。
 * 调用时,由于有多个连通分量,一次dfs无法全部遍历,
 * 	   所以:
 * 	   for(i=1;i<=n;i++)
 * 	   	   if(!dfn[i])
 * 	   	       tarjan(i);
 * */
void tarjan(int x)
{
	int i,j;
	dfn[x] = low[x] = ++index;
	for(i=head[x];i;i=edge[i].next)
	{
		j = edge[i].v;
		//if(j!=father)	
		//{
			if(!dfn[j])
			{
				tarjan(j,x);
				low[x] = min(low[x],low[j]);
			}else
				low[x] = min(low[x],dfn[j]);
		//}
	}
	
	if(low[x]==dfn[x])
	{
		label++;
		do
		{
			j = stack[deep--];
			lab[j] = label;
		}while(j!=x);
	}
	return;
}

抱歉!评论已关闭.