POJ_3352_Road Construction_割点_割边

Road Construction
Time Limit: 2000MS        Memory Limit: 65536K
Total Submissions: 10654        Accepted: 5269

Description

It's almost summer time, and that means that it's almost summer construction time! This year, the good people who are
in charge of the roads on the tropical island paradise of Remote Island would like to repair and upgrade the
various roads that lead between the various tourist attractions on the island.

The roads themselves are also rather interesting. Due to the strange customs of the island, the roads are arranged
so that they never meet at intersections, but rather pass over or under each other using bridges and tunnels. In this
 way, each road runs between two specific tourist attractions, so that the tourists do not become irreparably lost.

Unfortunately, given the nature of the repairs and upgrades needed on each road, when the construction company works
 on a particular road, it is unusable in either direction. This could cause a problem if it becomes impossible to
 travel between two tourist attractions, even if the construction company works on only one road at any particular time.

So, the Road Department of Remote Island has decided to call upon your consulting services to help remedy this problem.
 It has been decided that new roads will have to be built between the various attractions in such a way that in the
 final configuration, if any one road is undergoing construction, it would still be possible to travel between any two
  tourist attractions using the remaining roads. Your task is to find the minimum number of new roads necessary.

Input

The first line of input will consist of positive integers n and r, separated by a space, where 3 ≤ n ≤ 1000 is the
 number of tourist attractions on the island, and 2 ≤ r ≤ 1000 is the number of roads. The tourist attractions are
 conveniently labelled from 1 to n. Each of the following r lines will consist of two integers, v and w, separated by
  a space, indicating that a road exists between the attractions labelled v and w. Note that you may travel in either
   direction down each road, and any pair of tourist attractions will have at most one road directly between them.
   Also, you are assured that in the current configuration, it is possible to travel between any two tourist
   attractions.

Output

One line, consisting of an integer, which gives the minimum number of roads that we need to add.

Sample Input

Sample Input 1
10 12
1 2
1 3
1 4
2 5
2 6
5 6
3 7
3 8
7 8
4 9
4 10
9 10

Sample Input 2
3 3
1 2
2 3
1 3

Sample Output

Output for Sample Input 1
2

Output for Sample Input 2
0

*/
/*
题意:
 
    某个企业想把一个热带天堂岛变成旅游胜地,岛上有N个旅游景点,任意2个旅游景点之间有路径连通(注意不一定是直接连通)。
而为了给游客提供更方便的服务,该企业要求道路部门在某些道路增加一些设施。道路部门每次只会选择一条道路施工在该条道路施工
完毕前,其他道路依然可以通行。然而有道路部门正在施工的道路,在施工完毕前是禁止游客通行的。这就导致了在施工期间游客
可能无法到达一些景点。为了在施工期间所有旅游景点依然能够正常对游客开放,该企业决定搭建一些临时桥梁,
使得不管道路部门选在哪条路进行施工,游客都能够到达所有旅游景点。给出当下允许通行的R条道路,
问该企业至少再搭建几条临时桥梁,才能使得游客无视道路部门的存在到达所有旅游景点?


 给定一个连通的无向图G,至少要添加几条边,才能使其变为双连通图。

用Tarjan算法 求解每个low[i]值,然后求解所有的缩点(双联通分量个数)。

要添的边 = (缩点个数+1)/2;
 

#include <stdio.h>
#include <string.h>
#include <vector>
#include <algorithm>
using namespace std;
const int Max_N = 1002;
int n,m,num;
bool vis[Max_N];
int dfn[Max_N];
int low[Max_N];
int dist[Max_N];
vector<int> G[Max_N];

void init()
{
	int i;
	for(i=0;i<=n;i++)
	{
		G[i].clear();
	}
	memset(dist,0,sizeof(dist));
	memset(vis,false,sizeof(vis));
}

void add_edge(int a,int b)
{
	G[a].push_back(b);
	G[b].push_back(a);
}

void dfs(int x,int father)
{
	int i;
	vis[x] = true;
	num ++ ;
	dfn[x] = num;
	low[x] = num;
	for(i=0;i<G[x].size();i++)
	{
		int v = G[x][i];
		if(vis[v]==false)
		{
			dfs(v,x);
			low[x] = min(low[x],low[v]);
		}
		else if(vis[v]==true && v!=father)
		{
			low[x] = min(low[x],dfn[v]); 
		}
	}
}

int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		int i,j,a,b;
		for(i=0;i<m;i++)
		{
			scanf("%d%d",&a,&b);
			add_edge(a,b);
		}
		num = 0;
		dfs(1,1);
		int res = 0;
		for(i=1;i<=n;i++)
		{
			for(j=0;j<G[i].size();j++)
			{
				if(low[i]!=low[G[i][j]])
				{
					dist[low[i]] ++ ;
				}
			}
		} 
		for(i=1;i<=n;i++)
		{
			if(dist[i]==1)
			{
				res++;
			}
		}
		printf("%d\n",(res+1)>>1);
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值