边双连通分量模板题

Posted cutemush

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了边双连通分量模板题相关的知识,希望对你有一定的参考价值。

1:POJ3353 Road Construction

此题没有重边

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 1010
#define M 2020
using namespace std;
struct KSD
{
	int v,next;
}e[M];
int head[N],cnt;
inline void add(int u,int v)
{
	e[++cnt].v=v;
	e[cnt].next=head[u];
	head[u]=cnt;
}
int dfn[N],low[N],n,m;
int id[N],group,d[N];
int ans,edges; // 边-双个数、 桥个数
int stk[N],top;

void tarjan(int x,int p) 
// 边双连通分量,即无桥。
{
	int i,v,temp;
	dfn[x]=low[x]=++cnt;
	stk[++top]=x;
	for(i=head[x];i;i=e[i].next)
	{
		v=e[i].v;
		if(v==p)continue;
		if(!dfn[v])
		{
			tarjan(v,x);
			low[x]=min(low[x],low[v]);
		}
		else low[x]=min(low[x],dfn[v]);
//		if(dfn[x]<low[v])edges++; // 桥的数目
	}
	if(dfn[x]==low[x])
	{
		group++;
		do{
			temp=stk[top--];
			id[temp]=group;
			//第temp个点属于第group个连通块 
		}while(temp!=x);
	}
	return ;
}

int main()
{
//	freopen("test.in","r",stdin);
	int i,j,k;
	int a,b,c;
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		memset(head,0,sizeof(head));
		memset(dfn,0,sizeof(dfn));
		memset(d,0,sizeof(d));
		cnt=group=ans=0;

		for(i=1;i<=m;i++)
		{
			scanf("%d%d",&a,&b);
			add(a,b),add(b,a);
		}
		cnt=0;
		for(i=1;i<=n;i++)
		     if(!dfn[i])
			     tarjan(i,0);
		for(j=1;j<=n;j++)
			for(i=head[j];i;i=e[i].next)
				if(id[j]!=id[e[i].v])
				//有一条边从J-->e[i].v
				//e[i].v的入度加1 
				   d[id[e[i].v]]++;
		for(i=1;i<=n;i++)
		   if(d[i]==1)
		      ans++;

		printf("%d
",(ans+1)>>1);
	}

	return 0;
}

  

以上是关于边双连通分量模板题的主要内容,如果未能解决你的问题,请参考以下文章

hdu3394Railway双连通分量+模板详细解释

tarjan求边双连通分量模板

双连通分量和强连通分量的总结

割点桥模板以及点双连通边双连通

HDOJ2242解题报告边双连通分量

双连通分量