您的位置:首页 > 其它

【POJ3352】Road Construction tarjan求边-双连通分量,裸题模板题

2015-01-13 08:39 417 查看
转载请注明出处:http://blog.csdn.net/vmurder/article/details/42671851

其实我就是觉得原创的访问量比未授权盗版多有点不爽233。。。

裸题只给模板。

tarjan可以实现。

太水不发题解。

代码:

#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
,cnt;
inline void add(int u,int v)
{
	e[++cnt].v=v;
	e[cnt].next=head[u];
	head[u]=cnt;
}
int dfn
,low
,n,m;
int id
,group,d
;
int ans,edges; // 边-双个数、 桥个数
int stk
,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;
		}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])d[id[e[i].v]]++;
		for(i=1;i<=n;i++)if(d[i]==1)ans++;

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

	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: