poj 3352 (双联通缩点)

题意:给出一个无向联通图,求最少添加几条边让图是双联通图。

思路:先Tarjan缩点,(求出度数为1的双联通分量的个数+1)/2;

#include<stdio.h>
#include<string.h>
const int N=1100;
int dep[N],dfs[N],low[N],ans,idx,head[N],num;
struct edge
{
	int st,ed,next;
}e[N*100];
void addedge(int x,int y)
{
	e[num].st=x;e[num].ed=y;e[num].next=head[x];head[x]=num++;
	e[num].st=y;e[num].ed=x;e[num].next=head[y];head[y]=num++;
}
void Tarjan(int u,int id)
{
	int i,v;
	dfs[u]=low[u]=++idx;
	for(i=head[u];i!=-1;i=e[i].next)
	{
		if(i==(id^1))continue;
		v=e[i].ed;
		if(dfs[v]==-1)
		{
			Tarjan(v,i);
			low[u]=low[u]>low[v]?low[v]:low[u];
		}
		else low[u]=low[u]>dfs[v]?dfs[v]:low[u];
	}
}
int main()
{
	int i,n,m,x,y,sum;
	while(scanf("%d%d",&n,&m)!=-1)
	{
		memset(head,-1,sizeof(head));
		num=0;
		for(i=0;i<m;i++)
		{
			scanf("%d%d",&x,&y);
			addedge(x,y);
		}
		memset(dfs,-1,sizeof(dfs));
		ans=idx=0;
		Tarjan(1,-1);
		memset(dep,0,sizeof(dep));
		for(i=0;i<num;i+=2)
		{
			x=low[e[i].st];
			y=low[e[i].ed];
			if(x==y)continue;
			dep[x]++;
			dep[y]++;
		}
		sum=0;
		for(i=1;i<=idx;i++)
		{
			if(dep[i]==1)
				sum++;
		}
		printf("%d\n",(sum+1)/2);
	}
	return 0;
}

点赞