FZU 2112 并查集欧拉通路
Posted Unbelievable
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FZU 2112 并查集欧拉通路相关的知识,希望对你有一定的参考价值。
原题:http://acm.fzu.edu.cn/problem.php?pid=2112
首先是,票上没有提到的点是不需要去的。
然后我们先考虑这个图有几个联通分量,我们可以用一个并查集来维护,假设有n个联通分量,我们就需要n-1条边把他们连起来。
最后对于每个联通分量来说,我们要使它能一次走完,就是要求他是否满足欧拉通路,也就是这个联通分量中至多有2个度为奇数的点,每多出2个度为奇数的点,就多需要一条边(因为单个连通分量的所有点的度数之和为偶数,所以不可能存在奇数个奇数度数的点)。
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #define maxn 111111 5 using namespace std; 6 int f[maxn],du[maxn],odd[maxn],book[maxn]; 7 int getf(int v){ 8 if(f[v] == v){ 9 return v; 10 }else{ 11 f[v] = getf(f[v]); 12 return f[v]; 13 } 14 } 15 void merge(int u,int v){ 16 int a = getf(u); 17 int b = getf(v); 18 if(a!=b) 19 f[b] = a; 20 } 21 int main(){ 22 int t; 23 scanf("%d",&t); 24 while(t--){ 25 memset(du,0,sizeof(du));//统计每个节点的度数 26 memset(odd,0,sizeof(odd));//统计每个联通分量度数为奇数的节点个数 27 memset(book,0,sizeof(book));//标记该点是否需要去 28 int n,m; 29 scanf("%d%d",&n,&m); 30 for(int i = 1;i<=n;i++)//初始化 31 f[i] = i; 32 int u,v; 33 while(m--){ 34 scanf("%d%d",&u,&v); 35 du[u]++; 36 du[v]++; 37 book[u] = 1; 38 book[v] = 1; 39 merge(u,v); 40 } 41 int cnt = 0;//需要边的数量 42 for(int i = 1;i<=n;i++){ 43 if(book[i]){ 44 if(f[i] == i) 45 cnt++; 46 if(du[i]&1)//度数为奇数时,对其并查集根节点的值进行更新 47 odd[getf(i)]++; 48 } 49 } 50 for(int i = 1;i<=n;i++){ 51 if(f[i] == i) 52 cnt += max(0,(odd[i]-2)/2);//统计每个联通分量的度数为奇数的节点所需要的边的个数 53 } 54 printf("%d\n",cnt-1); 55 } 56 return 0; 57 }
以上是关于FZU 2112 并查集欧拉通路的主要内容,如果未能解决你的问题,请参考以下文章
POJ-2513 Colored Sticks---欧拉回路+并查集+字典树
POJ 1386 Play on Words(有向欧拉通路 连通图)