poj 3352 Road Construction(双连通图Tarjan求至少增加的边数)

大致题意:

某个企业想把一个热带天堂岛变成旅游胜地,岛上有N个旅游景点,任意2个旅游景点之间有路径连通(注意不一定是直接连通)。而为了给游客提供更方便的服务,该企业要求道路部门在某些道路增加一些设施。

道路部门每次只会选择一条道路施工,在该条道路施工完毕前,其他道路依然可以通行。然而有道路部门正在施工的道路,在施工完毕前是禁止游客通行的。这就导致了在施工期间游客可能无法到达一些景点。

为了在施工期间所有旅游景点依然能够正常对游客开放,该企业决定搭建一些临时桥梁,使得不管道路部门选在哪条路进行施工,游客都能够到达所有旅游景点。给出当下允许通行的R条道路,问该企业至少再搭建几条临时桥梁,才能使得游客无视道路部门的存在到达所有旅游景点?

至少增加的边数 =( 这棵树总度数为1的结点数 + 1 )/ 2


参考资料:http://blog.csdn.net/lyy289065406/article/details/6762370

                  https://www.byvoid.com/blog/biconnect/


#include <iostream>
#include <stdio.h>
using namespace std;
#define MAXV 5010
#define min(a,b) (a>b?b:a)

int n,m;
bool map[MAXV][MAXV];
bool vis[MAXV];
int low[MAXV],dfn[MAXV];
int count;
int cnt[MAXV];

void init(){
	memset(vis,0,sizeof(vis));
	memset(low,0,sizeof(low));
	memset(dfn,0,sizeof(dfn));
	count=0;
}

void dfs(int x,int pre){
	int i;
	vis[x]=1;
	low[x]=dfn[x]=++count;
	for(i=1;i<=n;i++){
		if(map[x][i]){
			if(!vis[i]){
				dfs(i,x);
				low[x]=min(low[x],low[i]);
			}
			if(vis[i]==1 && i!=pre){
				low[x]=min(low[x],dfn[i]);
			}
		}
	}
}

int main(){
	int a,b;
	int i,j;
	while(~scanf("%d%d",&n,&m)){
		memset(map,0,sizeof(map));
		while(m--){
			scanf("%d%d",&a,&b);
			map[a][b]=map[b][a]=1;
		}

		init();
		dfs(1,1);

		memset(cnt,0,sizeof(cnt));	
		for(i=1;i<=n;i++){					//计算每个点的度
			for(j=1;j<=n;j++)
				if(map[i][j]){
					if(low[i]!=low[j]){
						cnt[low[j]]++;
					}
				}
		}
		int ans=0;				//计算度为1的点的个数
		for(i=1;i<=n;i++){
			if(cnt[i]==1) ans++;
		}
		printf("%d\n",(ans+1)/2);
	}
	return 0;
}


你可能感兴趣的:(poj 3352 Road Construction(双连通图Tarjan求至少增加的边数))