题目链接:
http://poj.org/problem?id=3177
题目大意:
Bessie的农场有F块牧场,已知当前任意两个农场之间至少有一条路径相连(并不一定直接相连)
为了从某块牧场移动到另一块牧场,Bessie和她的伙伴经常需要经过腐烂的树林。奶牛们特别
反感经过不好走的路,于是Bessie决定在农场种再建几条路,使得在去某个地方时总能够有两
条完全独立的路可够选择。那么问题来了:F块牧场,R条路,问至少再修几条路就能使得农场
中任意两个牧场之间都有至少两条相互独立的路径。
思路:
为了使农场中任意两个牧场之间都有至少两条相互独立的路径。也就是把F块牧场看做点,R条
路看做是两个农场之间的双向边。那么问题就转换为:最少添加几条边,可以使图不存在割边。
也就是和POJ3352一样的问题:最少添加几条边,使得任意两个边连通分量之间相互双连通。
具体做法参考博文:http://blog.csdn.net/lianai911/article/details/43867789
注:此题比POJ3352多了一点,需要判重。。。所以我用了Map[][]数组。
AC代码:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; const int MAXN = 5050; const int MAXM = 50500; bool Map[MAXN][MAXN]; struct EdgeNode { int to; int next; }Edges[MAXM]; int Head[MAXN]; int dfn[MAXN],low[MAXN],Stack[MAXN],degree[MAXN]; int m,id,scc,lay,M,N; void AddEdges(int u,int v) { Edges[id].to = v; Edges[id].next = Head[u]; Head[u] = id++; } void TarjanBFS(int pos,int from) { //Stack[m++] = pos; dfn[pos] = low[pos] = ++lay; for(int i = Head[pos]; i != -1; i = Edges[i].next) { if(Edges[i].to == from) continue; if( !dfn[Edges[i].to] ) { TarjanBFS(Edges[i].to,pos); low[pos] = min(low[pos],low[Edges[i].to]); // if( dfn[pos] < low[Edges[i].to] ) // { // while(Stack[m--] != Edges[i].to); // } } else low[pos] = min(low[pos],low[Edges[i].to]); } } int main() { int u,v; while(~scanf("%d%d",&N,&M)) { memset(Head,-1,sizeof(Head)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(degree,0,sizeof(degree)); m = lay = scc = id = 0; memset(Map,0,sizeof(Map)); for(int i = 0; i < M; ++i) { scanf("%d%d",&u,&v); if(Map[u][v] == 0) { AddEdges(u,v); AddEdges(v,u); Map[u][v] = Map[v][u] = 1; } } TarjanBFS(1,-1); for(int i = 1; i <= N; ++i) { for(int j = Head[i]; j != -1; j = Edges[j].next) { if(low[i] != low[Edges[j].to]) degree[low[i]]++; } } int ans = 0; for(int i = 1; i <= N; ++i) if(degree[i] == 1) ans++; printf("%d\n",(ans+1)/2); } return 0; }