POJ 3177 Redundant Paths 双联通分量 割边

http://poj.org/problem?id=3177

这个妹妹我大概也曾见过的~~~我似乎还没写过双联通分量的blog,真是智障。

最少需要添多少条边才能使这个图没有割边。

边双缩点后图变成一棵树,( 树上度数为1的点的数目+1 ) / 2就是答案。

注意:

1.直接缩成一个点的时候特判一下(不需要加边)。

2.找割边同时用栈缩点的话要注意需要缩成一个点的是割边后面所有的点,能缩的时候直接判断末尾有没有到当前点就完事了,如果判断low来找割边后面所有的点是不准确的。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<queue>
 7 using namespace std;
 8 #define LL long long
 9 #define pa pair<int,int>
10 const int maxn=5010;
11 const LL minf=(LL)5e17;
12 int n,m;
13 struct nod{
14     int x,y,next;
15 }e[maxn*4];
16 int head[maxn]={},tot=1;
17 int dfn[maxn]={},low[maxn]={},cnt=0,tn=0;
18 int sta[maxn]={},bel[maxn]={},fa[maxn]={},tai=0;
19 int vis[maxn]={};
20 inline void init(int x,int y){
21     e[++tot].y=y;e[tot].next=head[x];head[x]=tot;
22 }
23 void dfs(int x,int p,int f){
24     dfn[x]=low[x]=++cnt;sta[++tai]=x;
25     for(int i=head[x];i;i=e[i].next){
26         if(i==p)continue;
27         if(!dfn[e[i].y]){
28             dfs(e[i].y,i^1,x);
29             low[x]=min(low[x],low[e[i].y]);
30         }
31         else low[x]=min(dfn[e[i].y],low[x]);
32     }
33     if(low[x]==dfn[x]){
34         tn++;
35         while(tai&&sta[tai]!=x){
36             bel[sta[tai--]]=tn;
37         }bel[sta[tai--]]=tn;
38         fa[tn]=f;
39     }
40 }
41 int main(){
42     scanf("%d%d",&n,&m);
43     int x,y;
44     for(int i=1;i<=m;i++){
45         scanf("%d%d",&x,&y);
46         init(x,y);init(y,x);
47     }
48     dfs(1,0,0);
49     if(tn==1){printf("0\n");return 0;}
50     for(int i=1;i<=tn;i++){fa[i]=bel[fa[i]];vis[fa[i]]++;}
51     int ans=1;
52     if(vis[tn]==1)ans=2;
53     for(int i=1;i<=tn;i++)if(!vis[i])++ans;
54     printf("%d\n",ans/2);
55     return 0;
56 }
View Code

猜你喜欢

转载自www.cnblogs.com/137shoebills/p/9061656.html
今日推荐