【边双连通】poj 3352 Road Construction

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

【题意】

给定一个连通的无向图,求最少加多少条边使得这个图变成边双连通图

【AC】

  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
",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  
View Code
原文地址:https://www.cnblogs.com/itcsl/p/7771140.html