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 }

 

你可能感兴趣的:(poj)