POJ3692 Kindergarten【二分图最大独立集】

题目链接:

http://poj.org/problem?id=3692


题目大意:

幼儿园里边有N个男孩和M个女孩,所有男生之间都互相认识,所有女生之间也都相互认识。

还有k对关系,表示某个男孩和某个女孩认识。现在要选择一些学生组成一个集合,使得这个

集合中所有的人都认识,求这个集合中最多能有多少人。


思路:

建立二分图,图的一边为男生,另一边为女生。不能直接选取认识关系来建边,应该选取不认

识的人建边,也就是认识关系的补集作为边集。这样匹配的两个人都是不认识的,求出来的最

大匹配数就是最多有多少对人相互不认识。而最大独立集 = N + M - 最大匹配数,就求出了最

多能能多少个同学组成一个集合,使得集合中所有人都相互认识。

所以建图时,先将Map[][]初始化为1,认识的人赋值为0,然后求最大匹配数,从而得到最大独

立集。


AC代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN = 220;

bool Map[MAXN][MAXN];
bool Mask[MAXN];

int NX,NY;
int cx[MAXN],cy[MAXN];

int FindPath(int u)
{
    for(int i = 1; i <= NY; ++i)
    {
        if(Map[u][i] && !Mask[i])
        {
            Mask[i] = 1;
            if(cy[i] == -1 || FindPath(cy[i]))
            {
                cy[i] = u;
                cx[u] = i;
                return 1;
            }
        }
    }
    return 0;
}


int MaxMatch()
{
    int res = 0;
    for(int i = 1; i <= NX; ++i)
        cx[i] = -1;
    for(int i = 1; i <= NY; ++i)
        cy[i] = -1;

    for(int i = 1; i <= NX; ++i)
    {
        if(cx[i] == -1)
        {
            for(int j = 1; j <= NY; ++j)
                Mask[j] = 0;
            res += FindPath(i);
        }
    }
    return res;
}

int main()
{
    int M,u,v,kase = 0;
    while(~scanf("%d%d%d",&NX,&NY,&M) && (NX||NY||M))
    {
        for(int i = 1; i <= NX; ++i)
            for(int j = 1; j <= NY; ++j)
                Map[i][j] = 1;
        for(int i = 1; i <= M; ++i)
        {
            scanf("%d%d",&u,&v);
            Map[u][v] = 0;
        }
        printf("Case %d: %d\n",++kase,NX+NY-MaxMatch());
    }

    return 0;
}


你可能感兴趣的:(POJ3692 Kindergarten【二分图最大独立集】)