Problem - 216B - Codeforces

题目链接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

      

View Code
 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 }

 

posted @ 2013-03-15 19:51  zlyblog  阅读(322)  评论(0编辑  收藏  举报