题目链接http://codeforces.com/problemset/problem/216/B
题意:有一群人要踢足球,但是在这些人中有几对人存在敌对的关系,要求每个队的人数相等并且同一个队中不存在互为敌对关系的人,每个人最多只会讨厌两个人,如果a讨厌b,那么b也会讨厌a,问你至少有多少人不能参加比赛。
并查集的灵活应用:
我们先把存在敌对关系的人之间连一条边,通过并查集把他们放在一个集合里,每次加入一条边时先判断这一条边的两点是否已存在同一个集合里,如果是,那么就构成了环,注意题目所说的每个人最多只会讨厌两个人,自己画画图就知道了,对环进行0,1,染色,可知如果环里面的人数为奇数,那么就需要提一个人出来,才能满足一个队中没有互相讨厌的人,否则就会有冲突。用总人数-奇数环的个数,如果该数为偶数,直接输出奇数环的个数,如果为奇数,则要在奇数环的个数上在剔除一个人。
输入: i 1 2 4 3 5
5 4 1 → 2 → 4 3 → 5
1 2 vis[i] 0 0 0 0 0
2 4 num[i] 1 1 1 1 1
5 3 father[i] 1 2 4 3 5
1 4
输出:
1

1 #include<stdio.h> 2 #define N 110 3 int father[110],vis[110],num[110]; 4 int n,m,a,b; 5 int find(int x) 6 { 7 if(x!=father[x]) 8 return father[x]=find(father[x]); 9 } 10 int main() 11 { 12 int i,c,fa,fb; 13 while(scanf("%d%d",&n,&m)!=EOF) 14 { 15 for(i=1;i<=n;i++) 16 { 17 vis[i]=0; 18 num[i]=1; 19 father[i]=i; 20 } 21 for(i=1;i<=m;i++) 22 { 23 scanf("%d%d",&a,&b); 24 fa=find(a); 25 fb=find(b); 26 if(fa==fb) 27 { 28 vis[fa]=1; 29 vis[fb]=1; 30 } 31 if(fa!=fb) 32 { 33 father[fa]=fb; 34 num[fb]+=num[fa]; 35 } 36 } 37 c=0; 38 for(i=1;i<=n;i++) 39 { 40 if(father[i]==i&&vis[i]==1) 41 c+=num[i]%2; 42 } 43 printf("%d\n",n-(n-c)/2*2); 44 45 } 46 return 0; 47 }