【边双连通】poj 3352 Road Construction
http://poj.org/problem?id=3352
【题意】
给定一个连通的无向图,求最少加多少条边使得这个图变成边双连通图
【AC】
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //#include<bits/stdc++.h> 2 #include<iostream> 3 #include<cstdio> 4 #include<string> 5 #include<cstring> 6 7 using namespace std; 8 typedef long long ll; 9 int n,m; 10 const int maxn=1e3+2;; 11 const int maxm=2*maxn; 12 struct node 13 { 14 int to; 15 int nxt; 16 }e[maxm]; 17 int tot; 18 int head[maxn]; 19 int vis[maxn]; 20 int dfn[maxn]; 21 int id; 22 int low[maxn]; 23 int du[maxn]; 24 void init() 25 { 26 tot=0; 27 memset(head,-1,sizeof(head)); 28 memset(dfn,0,sizeof(dfn)); 29 id=0; 30 memset(low,0,sizeof(low)); 31 memset(du,0,sizeof(du)); 32 } 33 void add(int u,int v) 34 { 35 e[tot].to=v; 36 e[tot].nxt=head[u]; 37 head[u]=tot++; 38 } 39 void tarjan(int u,int pa) 40 { 41 vis[u]=1; 42 low[u]=dfn[u]=++id; 43 for(int i=head[u];i!=-1;i=e[i].nxt) 44 { 45 int v=e[i].to; 46 if(v==pa) continue; 47 if(!vis[v])//树边 48 { 49 tarjan(v,u); 50 low[u]=min(low[u],low[v]); 51 } 52 else if(vis[v]==1)//回退边,vis[v]==2是横向边,不做操作 53 { 54 low[u]=min(low[u],dfn[v]); 55 } 56 } 57 vis[u]=2; 58 } 59 void solve() 60 { 61 memset(vis,0,sizeof(vis)); 62 for(int i=1;i<=n;i++) 63 { 64 if(!vis[i]) tarjan(i,i); 65 } 66 for(int u=1;u<=n;u++) 67 { 68 for(int i=head[u];i!=-1;i=e[i].nxt) 69 { 70 int v=e[i].to; 71 if(low[u]!=low[v]) 72 { 73 du[low[u]]++; 74 } 75 } 76 } 77 int cnt=0; 78 for(int i=1;i<=n;i++) 79 { 80 if(du[i]==1) 81 { 82 cnt++; 83 } 84 } 85 int ans=(cnt+1)/2; 86 printf("%d\n",ans); 87 88 } 89 int main() 90 { 91 while(~scanf("%d%d",&n,&m)) 92 { 93 init(); 94 int u,v; 95 for(int i=1;i<=m;i++) 96 { 97 scanf("%d%d",&u,&v); 98 add(u,v); 99 add(v,u); 100 } 101 solve(); 102 } 103 return 0; 104 } 105