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