HDU 3018 Ant Trip (并查集求连通块数+欧拉回路)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3018
题目大意:有n个点,m条边,人们希望走完所有的路,且每条道路只能走一遍。至少要将人们分成几组。
解题思路:先用并查集求出所有的连通块,然后判断每个连通块内点的度数,如果有奇数点则需要的组数ans+=奇数点/2;反之,所需组数ans+=1。注意:如果遇到孤立点即度数为0的点则不用算进去,因为没有跟他相连的边。
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 #define CLR(arr,val) memset(arr,val,sizeof(arr)) 6 using namespace std; 7 const int N=1e6+5; 8 9 int n,m; 10 int deg[N],root[N],num[N];//num[i]记录集合i内的奇数点个数 11 12 void init(){ 13 CLR(deg,0); 14 CLR(num,0); 15 for(int i=1;i<=n;i++) 16 root[i]=i; 17 } 18 19 int find(int x){ 20 return root[x]==x?x:root[x]=find(root[x]); 21 } 22 23 int main(){ 24 while(~scanf("%d%d",&n,&m)){ 25 init(); 26 for(int i=1;i<=m;i++){ 27 int u,v,x,y; 28 scanf("%d%d",&u,&v); 29 x=find(u); 30 y=find(v); 31 deg[u]++; 32 deg[v]++; 33 if(x!=y) 34 root[x]=y; 35 } 36 for(int i=1;i<=n;i++){ 37 if(deg[i]%2==1) 38 num[find(i)]++; 39 } 40 int ans=0; 41 for(int i=1;i<=n;i++){ 42 if(deg[i]==0) 43 continue; 44 if(find(i)==i){ 45 if(num[i]==0) 46 ans++; 47 else 48 ans+=num[i]/2; 49 } 50 } 51 printf("%d\n",ans); 52 } 53 return 0; 54 }