【缩点】Redundant Paths

传送舱:POJ3177

题意:求一张无向图至少加多少条边后双连通


思路:缩点后无向图变为树,答案即为(叶子结点个数+1)/2 因为将2个叶子结点连起来后一条链双连通


直接贴代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define N 30000
int n,m,tot,sum,clock,top,cnt,x[N],y[N],dfn[N],low[N],stack[N],belong[N],head[N],f[N];
bool instack[N];
struct edge{int v,nxt,ID;}e[N];
void add(int x,int y,int ID){e[++tot].v=y; e[tot].ID=ID; e[tot].nxt=head[x]; head[x]=tot;}
void tarjan(int u,int ID){
dfn[u]=low[u]=++clock; stack[top++]=u; instack[u]=1;
for (int i=head[u];i;i=e[i].nxt){
if (e[i].ID==ID) continue;
int v=e[i].v;
if (!dfn[v]){tarjan(v,e[i].ID); low[u]=min(low[u],low[v]);}
else if (instack[v]) low[u]=min(low[u],dfn[v]);
}
if (low[u]==dfn[u]){
cnt++; int v;
do {v=stack[--top]; belong[v]=cnt; instack[top]=0;} while (u!=v);
}
}
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++){scanf("%d%d",&x[i],&y[i]); add(x[i],y[i],i); add(y[i],x[i],i);}
tarjan(1,0);
for (int i=1;i<=m;i++)
if (belong[x[i]]!=belong[y[i]]){f[belong[x[i]]]++; f[belong[y[i]]]++;}
for (int i=1;i<=cnt;i++) if (f[i]==1) sum++;
printf("%d\n",(sum+1)>>1);
return 0;
}