边双联通分量(构造边双联通图)

Posted Kurokey

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了边双联通分量(构造边双联通图)相关的知识,希望对你有一定的参考价值。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstdlib>
  4 #include <cmath>
  5 #include <algorithm>
  6 #include <cstring>
  7 #include <stack>
  8 #include <cctype>
  9 #include <queue>
 10 #include <string>
 11 #include <vector>
 12 #include <set>
 13 #include <map>
 14 #include <climits>
 15 #define lson root<<1,l,mid
 16 #define rson root<<1|1,mid+1,r
 17 #define fi first
 18 #define se second
 19 #define ping(x,y) ((x-y)*(x-y))
 20 #define mst(x,y) memset(x,y,sizeof(x))
 21 #define mcp(x,y) memcpy(x,y,sizeof(y))
 22 #define Min(x,y) (x<y?x:y)
 23 #define Max(x,y) (x>y?x:y)
 24 using namespace std;
 25 #define gamma 0.5772156649015328606065120
 26 #define MOD 1000000007
 27 #define inf 0x3f3f3f3f
 28 #define N 11005
 29 #define maxn 5005
 30 typedef long long LL;
 31 typedef pair<int,int> PII;
 32 
 33 stack<int>sk;
 34 int n,m,hcnt,deep,block,leaf;
 35 int d[maxn],dfn[maxn],low[maxn],head[maxn];
 36 int color[maxn],vis[maxn];
 37 struct Node{
 38     int to,next;
 39     Node(){}
 40     Node(int a,int b):to(a),next(b){}
 41 }node[N<<1];
 42 
 43 inline void add(int x,int y){
 44     node[hcnt]=Node(y,head[x]);
 45     head[x]=hcnt++;
 46 }
 47 
 48 inline void init(){
 49     while(!sk.empty())sk.pop();
 50     mst(vis,0);
 51     mst(head,-1);
 52     mst(d,0);
 53     mst(dfn,0);
 54     hcnt=deep=0;
 55     block=leaf=0;
 56 }
 57 
 58 void dfs(int x,int fa){
 59     int flag=1;  ///这个不是必要的,有重边时有效
 60     sk.push(x);
 61     vis[x]=1;
 62     low[x]=dfn[x]=++deep;
 63     for(int i=head[x];~i;i=node[i].next){
 64         int e=node[i].to;
 65         if(e==fa&&flag){flag=0;continue;}
 66         if(vis[e])low[x]=min(low[x],dfn[e]);
 67         else if(!dfn[e]){
 68             dfs(e,x);
 69             low[x]=min(low[x],low[e]);
 70         }
 71     }
 72     if(low[x]==dfn[x]){
 73         ++block;    ///缩点
 74         int co;
 75         do{
 76             co=sk.top();sk.pop();
 77             vis[co]=0;
 78             color[co]=block;
 79         }while(co!=x);
 80     }
 81 }
 82 
 83 int main(){
 84     int i,j,group,Case=0,x,y;
 85     while(scanf("%d%d",&n,&m)!=EOF){
 86         init();
 87         for(i=0;i<m;++i){
 88             scanf("%d%d",&x,&y);
 89             add(x,y);
 90             add(y,x);
 91         }
 92         for(i=1;i<=n;++i){
 93             if(!dfn[i])dfs(i,-1);
 94         }
 95         if(block==1){printf("0\n");continue;}   ///判断是否已经是双连通图
 96         for(i=1;i<=n;++i)
 97         for(j=head[i];~j;j=node[j].next){
 98             int e=node[j].to;
 99             if(color[i]!=color[e])
100                 ++d[color[i]];   ///d数组保留的是缩点后每个点的度数
101         }
102         for(i=1;i<=block;++i){
103             if(d[i]==0)leaf+=2;  ///如果有孤立的点,叶子节点加2
104             else if(d[i]==1)++leaf;
105         }
106         printf("%d\n",(leaf+1)/2);
107     }
108     return 0;
109 }

 

以上是关于边双联通分量(构造边双联通图)的主要内容,如果未能解决你的问题,请参考以下文章

双联通的tarjan算法

poj-3177(并查集+双联通分量+Tarjan算法)

边双联通分量与割边

POJ3352边双连通分量缩点添加最少无向边构造边双

4.18 省选模拟赛 桥 边双联通分量 长链剖分维护贪心

边双联通分量