poj 3177 边双联通 **

题意:给定一个连通的无向图G,至少要添加几条边,才能使其变为双连通图。

链接:点我

kuangbin模板题,分析链接:点我

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <iostream>
  4 #include <algorithm>
  5 #include <map>
  6 using namespace std;
  7 const int MAXN = 5010;//点数
  8 const int MAXM = 20010;//边数,因为是无向图,所以这个值要*2
  9 struct Edge
 10 {
 11 int to,next;
 12 bool cut;//是否是桥标记
 13 }edge[MAXM];
 14 int head[MAXN],tot;
 15 int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];//Belong数组的值是1~block
 16 int Index,top;
 17 int block;//边双连通块数
 18 bool Instack[MAXN];
 19 int bridge;//桥的数目
 20 void addedge(int u,int v)
 21 {
 22     edge[tot].to = v;edge[tot].next = head[u];edge[tot].cut=false;
 23     head[u] = tot++;
 24 }
 25 void Tarjan(int u,int pre)
 26 {
 27     int v;
 28     Low[u] = DFN[u] = ++Index;
 29     Stack[top++] = u;
 30     Instack[u] = true;
 31     for(int i = head[u];i != -1;i = edge[i].next)
 32     {
 33         v = edge[i].to;
 34         if(v == pre)continue;
 35         if( !DFN[v] )
 36         {
 37             Tarjan(v,u);
 38             if( Low[u] > Low[v] )Low[u] = Low[v];
 39             if(Low[v] > DFN[u])
 40             {
 41                 bridge++;
 42                 edge[i].cut = true;
 43                 edge[i^1].cut = true;
 44             }
 45         }
 46         else if( Instack[v] && Low[u] > DFN[v] )
 47         Low[u] = DFN[v];
 48     }
 49     if(Low[u] == DFN[u])
 50     {
 51         block++;
 52         do
 53         {
 54             v = Stack[--top];
 55             Instack[v] = false;
 56             Belong[v] = block;
 57         }
 58         while( v!=u );
 59     }
 60 }
 61 void init()
 62 {
 63     tot = 0;
 64     memset(head,-1,sizeof(head));
 65 }
 66 int du[MAXN];//缩点后形成树,每个点的度数
 67 void solve(int n)
 68 {
 69     memset(DFN,0,sizeof(DFN));
 70     memset(Instack,false,sizeof(Instack));
 71     Index = top = block = 0;
 72     Tarjan(1,0);
 73     int ans = 0;
 74     memset(du,0,sizeof(du));
 75     for(int i = 1;i <= n;i++)
 76         for(int j = head[i];j != -1;j = edge[j].next)
 77             if(edge[j].cut)
 78                 du[Belong[i]]++;
 79     for(int i = 1;i <= block;i++)
 80         if(du[i]==1)
 81             ans++;
 82     //找叶子结点的个数ans,构造边双连通图需要加边(ans+1)/2
 83     printf("%d\n",(ans+1)/2);
 84 }
 85 int main()
 86 {
 87     int n,m;
 88     int u,v;
 89     while(scanf("%d%d",&n,&m)==2)
 90     {
 91         init();
 92         while(m--)
 93         {
 94             scanf("%d%d",&u,&v);
 95             addedge(u,v);
 96             addedge(v,u);
 97         }
 98         solve(n);
 99     }
100     return 0;
101 }

 

posted @ 2015-07-03 09:46  miao_a_miao  阅读(134)  评论(0编辑  收藏  举报