Codeforces Round #133 (Div. 2) B. Forming Teams B. Forming Teams 并查集的扩张

http://codeforces.com/problemset/problem/216/B

题意:

有n个人,要求你将他们平均分成两组进行球赛。给出m个敌对关系,每个人最多有两个敌对的人,属于敌对关系的两个人不能分到同一小组里面。输出不能被分到两个小组最少人数。

思路:

和poj的食物链题目类似,这里利用并查集的长度记录关系,每出现一个敌对关系就将他们合并。距离为0表示可以属于同一组,1表示是敌对关系。当出现的两个敌对关系在之前已经确定为同类关系,必然将其剔除。记录剔除的个数,最后检查剔除这些人之后的人数是偶数。

View Code
#include <iostream>

#include <cstdio>

#include <cstdlib>

#include <cstring>

#include <algorithm>

#include <cmath>

#include <queue>

#include <stack>

#include <set>

#include <map>

#include <string>



#define CL(a,num) memset((a),(num),sizeof(a))

#define iabs(x)  ((x) > 0 ? (x) : -(x))

#define Min(a,b) (a) > (b)? (b):(a)

#define Max(a,b) (a) > (b)? (a):(b)



#define ll long long

#define inf 0x7f7f7f7f

#define MOD 1073741824

#define lc l,m,rt<<1

#define rc m + 1,r,rt<<1|1

#define pi acos(-1.0)

#define test puts("<------------------->")

#define maxn 100007

#define M 1000007

#define N 107

using namespace std;

//freopen("data.in","r",stdin);

int f[N],dep[N];

int num ;



int find(int x){

    if (x != f[x]){

        int tmp = f[x];

        f[x] = find(f[x]);

        dep[x] = (dep[tmp] + dep[x])%2;

    }

    return f[x];

}

void Union(int x,int y){

    int tx = find(x);

    int ty = find(y);

    if (tx != ty){

        f[ty] = tx;

        dep[ty] = (dep[y] + dep[x] + 1)%2;

    }

    else{

        if (iabs(dep[x] - dep[y])%2 == 0) num++;

    }

}

int main(){

   // freopen("data.in","r",stdin);

    int n,m;

    int i;

    int a,b;

    while (~scanf("%d%d",&n,&m)){

        CL(dep,0); num = 0;

        for (i = 1; i <= n; ++i) f[i] = i;

        for (i = 1; i <= m; ++i){

            scanf("%d%d",&a,&b);

            Union(a,b);

        }

        if ((n - num)&1) printf("%d\n",num + 1);

        else printf("%d\n",num);

    }

    return 0;

}

你可能感兴趣的:(codeforces)