边双连通分量 jarjan (poj 3177)

大意:给定一个无向连通图,判断至少加多少的边,才能使任意两点之间至少有两条的独立的路(没有公共的边,但可以经过同一个中间的顶点)。

思路:在同一个双连通分量里的所有的点可以看做一个点,收缩后,新图是一棵树,树的边便是原图的桥。现在问题转化为“在树中至少添加多少条边能使图变成边双连通图”,即添加的边的个数=(树中度为一的节点数目+1)/2,用trajan算法求双联通分量

这是一个模板

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<string.h>
 4 #include<algorithm>
 5 #include<queue>
 6 #include<vector>
 7 using namespace std;
 8 const int maxn=1e4+10;
 9 struct node
10 {
11     int v,cut,nxt;
12 }G[2*maxn];
13 int cnt;
14 int head[maxn];
15 int Stack[maxn];
16 int instack[maxn];
17 int low[maxn],dfn[maxn];
18 int belong[maxn],du[maxn];
19 int block,index;
20 int bridge,top;
21 void init()
22 {
23     cnt=0;
24     memset(head,-1,sizeof(head));
25 }
26 void build(int u,int v)
27 {
28     G[cnt].v=v;G[cnt].nxt=head[u];G[cnt].cut=0;head[u]=cnt++;
29 }
30 void tarjan(int u,int pre)
31 {
32     low[u]=dfn[u]=++index;
33     Stack[top++]=u;
34     instack[u]=1;
35     int v;
36     for(int i=head[u];i!=-1;i=G[i].nxt){
37         v=G[i].v;
38         if(pre==v) continue;
39         if(!dfn[v]){
40             tarjan(v,u);
41             low[u]=min(low[u],low[v]);
42             if(low[v]>dfn[u]){
43                 bridge++;
44                 G[i].cut=1;
45                 G[i^1].cut=1;
46             }
47         }
48         else if(low[u]>dfn[v]&&instack[v]) low[u]=dfn[v];
49     }
50     if(low[u]==dfn[u]){
51         block++;
52         do{
53             v=Stack[--top];
54             instack[v]=0;
55             belong[v]=block;
56         }while(v!=u);
57     }
58 }
59 void solve(int n)
60 {
61     int i,j;
62     int index=0;
63     bridge=0;
64     top=0;
65     block=0;
66     memset(low,0,sizeof(low));
67     memset(dfn,0,sizeof(dfn));
68     memset(belong,0,sizeof(belong));
69     memset(instack,0,sizeof(instack));
70     tarjan(1,0);
71     for(i=1;i<=n;i++){
72         for(j=1;j!=-1;j=G[j].nxt){
73             if(G[j].cut)
74             du[belong[i]]++;
75         }
76     }
77     int ans=0;
78     for(i=1;i<=block;i++){
79         if(du[i]==1)
80         ans++;
81     }
82     printf("%d\n",(ans+1)/2);
83 }
84 int main()
85 {
86     int n,m;
87     while(~scanf("%d%d",&n,&m)){
88         init();
89         for(int i=0;i<m;i++){
90             int u,v;
91             scanf("%d%d",&u,&v);
92             build(u,v);
93             build(v,u);
94         }
95         solve(n);
96     }
97     return 0;
98 }

 

posted @ 2019-10-28 20:47  古比  阅读(189)  评论(0编辑  收藏  举报