POJ3177(Redundant Paths)

Redundant Paths

Description

In order to get from one of the F (1 <= F <= 5,000) grazing fields (which are numbered 1…F) to another field, Bessie and the rest of the herd are forced to cross near the Tree of Rotten Apples. The cows are now tired of often being forced to take a particular path and want to build some new paths so that they will always have a choice of at least two separate routes between any pair of fields. They currently have at least one route between each pair of fields and want to have at least two. Of course, they can only travel on Official Paths when they move from one field to another.

Given a description of the current set of R (F-1 <= R <= 10,000) paths that each connect exactly two different fields, determine the minimum number of new paths (each of which connects exactly two fields) that must be built so that there are at least two separate routes between any pair of fields. Routes are considered separate if they use none of the same paths, even if they visit the same intermediate field along the way.

There might already be more than one paths between the same pair of fields, and you may also build a new path that connects the same fields as some other path.
Input

Line 1: Two space-separated integers: F and R

Lines 2…R+1: Each line contains two space-separated integers which are the fields at the endpoints of some path.
Output

Line 1: A single integer that is the number of new paths that must be built.
Sample Input

7 7
1 2
2 3
3 4
2 5
4 5
5 6
5 7

Sample Output
2

思路

有N個牧場(牧場編號1~N),Bessie 要從一個牧場到另一個牧場,要求至少要有2條獨立的路可以走。現已有M條路,求至少要新建多少條路,使得任何兩個牧場之間至少有兩條獨立的路。兩條獨立的路是指:沒有公共邊的路,但可以經過同一個中間頂點。這道題和POJ3352差不多,不同的就是這道題有重邊。

  1. Tarjan + 縮點,統計縮點度爲1的數目ans,最後要加的邊的數量就是(ans + 1) / 2。
  2. 重複邊處理,要麼直接開二維bool類型鄰接矩陣,簡單又方便
  3. 要麼用Set容器去重一下,遇到重複邊就不加入,存圖方式隨意。
  4. 去重完重複的邊直接跑裸的Tarjan,最後根據low值進行縮點找答案就可以了。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <stack>
#include <set>
#include <cmath>
using namespace std;
const int maxn = 5005;
struct edge{
	int from;
	int to;
	int next;
}e[maxn<<1];
set<int>st;
int low[maxn];
int d[maxn];
int head[maxn];
int cnt,tot;
inline void addedge(int x,int y)
{
	e[tot].from = x;
	e[tot].to = y;
	e[tot].next = head[x];
	head[x] = tot++;
}
inline void clear_set()
{
	tot = cnt = 0;
	memset(head,-1,sizeof(head));
	memset(low,0,sizeof(low));
	memset(d,0,sizeof(d));
	st.clear();
}
inline void tarjan(int x,int fx)
{
	low[x] = ++cnt;
	for(int i = head[x];~i;i = e[i].next){
		int y = e[i].to;
		if(y == fx)		continue;
		if(!low[y]){
			tarjan(y,x);	
		}
		low[x] = min(low[x],low[y]);
	}
}
int main()
{
	int n,m;
	while(~scanf("%d%d",&n,&m)){
		clear_set();
		int x,y;
		for(int i = 0;i < m;i++){
			scanf("%d%d",&x,&y);
			int s1 = x*10000 + y;				//加權計算一個得到答案,便於去重
			int s2 = y*10000 + x;				
			if(st.count(s1) == 0){
				addedge(x,y);	addedge(y,x); 
				st.insert(s1);	st.insert(s2);
			}
		}
		tarjan(1,-1); 
		for(int i = 0;i < tot;i++){				//無向圖邊數是2*m或者tot。
			x = e[i].from;
			y = e[i].to;
			if(low[x] != low[y]){
				d[low[x]]++;
			}
		}
		int ans = 0;
		for(int i = 1;i <= n;i++){
			if(d[i] == 1){
				ans++;
			}
		}
		printf("%d\n",(ans+1)/2);
	}
	return 0;	
}

願你走出半生,歸來仍是少年~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章