来源:http://poj.org/problem?id=3177
题意:给一个图,求最少需要添加几条边才能使任意两个点之间有至少两条路径。路径是不包括重边的,比如1 2 和2 1是一条路。
思路:其实就是一个求割边然后缩点,缩点之后求度为1的点即可。我写的这道题其实是有bug了,只不过这道题数据水了才过了,正常情况下是过不了的。统计度为1的时候不知道怎么能够消除重边的影响。附有bug的代码:
#include <iostream>
#include <cstdio>
#include <string.h>
#include <vector>
using namespace std;
#define CLR(arr,val) memset(arr,val,sizeof(arr))
const int N = 5010;
vector<int> vv[N];
int low[N],dfn[N],vis[N],numblock[N],head[N],instack[N],degree[N],use[1010][1010];
int timeorder,numpoint,numroad,numedge,numss,numcnt;
struct edge{
int lp,rp,next;
}ee[N*2];
void init(){
CLR(low,0);
CLR(dfn,0);
CLR(vis,0);
CLR(degree,0);
CLR(head,-1);
CLR(numblock,0);
timeorder = 0;
numedge = 0;
numss = 0;
numcnt = 0;
}
void add_edge(int x,int y){
ee[numedge].lp = x;
ee[numedge].rp = y;
ee[numedge].next = head[x];
head[x] = numedge++;
}
void dfs(int x,int fa){
timeorder++;
low[x] = dfn[x] = timeorder;
vis[x] = 1;
numss++;
instack[numss] = x;
for(int i = head[x]; i != -1; i = ee[i].next){
int y = ee[i].rp;
if(y == fa)continue;
if(!vis[y]){
dfs(y,x);
low[x] = min(low[x],low[y]);
if(low[y] > dfn[x]){
numcnt++;
while(1){
int tt = instack[numss];
numblock[tt] = numcnt;
if(instack[numss--] == y)
break;
}
}
}
else
low[x] = min(low[x],dfn[y]);
}
}
int main(){
//freopen("1.txt","r",stdin);
while(scanf("%d%d",&numpoint,&numroad) != EOF){
init();
int x,y;
while(numroad--){
scanf("%d%d",&x,&y);
add_edge(x,y);
add_edge(y,x);
}
dfs(1,1);
bool flag = false;
while(numss){
flag = true;
int tt = instack[numss--];
numblock[tt] = numcnt+1;
}
if(flag) numcnt++;
CLR(use,0);
for(int i = 0; i < numedge; i += 2){
int x = ee[i].lp;
int y = ee[i].rp;
if(use[x][y])continue;
use[x][y] = use[y][x] = 1;
if(numblock[x] != numblock[y]){
degree[numblock[x]]++;
degree[numblock[y]]++;
}
}
int ans = 0;
if(numcnt == 1){
printf("0\n");
continue;
}
for(int i = 1; i <= numcnt; ++i)
if(degree[i] == 1)
ans++;
printf("%d\n",(ans+1)/2);
}
return 0;
}