Ant Trip(欧拉回路+并查集)
Ant Trip
输入格式
输出格式
样例
数据范围与提示
1≤N≤10^5,0≤M≤2×105,1<=a,b<=N
思路:
It's also a good problem
原图应是由若干个无向连通图组成的
当这个无向连通图只有一个点时,这是一个孤立点,不做操作
当这个无向连通图是一条欧拉回路或欧拉路径时,只需要一笔画即可,sum++;
当这个无向连通图有大于2个奇度点,需要用奇度点的个数的二分之一笔画完,为什么?因为一笔可以消掉两个奇度点。由于对称性的缘故,一条边的左右两端点度数分别加一,倘若原来两点都是奇度点,则两端点都会变成偶度点,反之亦然,倘若两端点度数的奇偶性不同,一者为奇一者为偶,与这两点对应的点一定有奇数个奇度点,所以一个无向连通图中不可能存在奇数个奇度点,所以只需/2即可
当然可以用并查集维护每个无向连通图
上代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
int n,m,fa[100040],de[100004],sum[100040],num[100004];
void init(){
memset(de,0,sizeof(de));
memset(sum,0,sizeof(sum));
memset(num,0,sizeof(num));
rep(i,1,n) fa[i]=i;
}
int find(int x){
if(fa[x]==x) return x;
else return fa[x]=find(fa[x]);
}
int main(){
freopen("1.txt","r",stdin) while(~scanf("%d%d",&n,&m)){
int s=0;
init();
rep(i,1,m){
int a,b;
scanf("%d%d",&a,&b);
++de[a]; ++de[b];
a=find(a); b=find(b);
if(a!=b) fa[a]=b;
}
rep(i,1,n){
if(de[i]&1) sum[find(i)]++;
num[find(i)]++;
}
rep(i,1,n){
if(num[i]==0 || num[i]==1) continue;
else if(sum[i]==0) ++s;
else s+=(sum[i]/2);
}
printf("%d\n",s);
}
return 0;
}

浙公网安备 33010602011771号