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
",ans);
52     }
53     return 0;
54 }
原文地址:https://www.cnblogs.com/fu3638/p/7979188.html