poj 3692 最大团(二分图匹配,最大独立集)

http://poj.org/problem?id=3692
题意:
每个男生之间都相互认识,每个女生之间都相互认识,每个男生可能认识部分女生。求一个集合里面的人相互都认识,这个集合的人数最多是多少。
思路:
相互都认识,如果把认识关系当做边的话,那么要求的就是最大完全子图(也叫最大团)。
可以发现男生和女生自身都是一个完全子图,所以按照认识关系建图的话,违背了二分图的原则。思考用不认识的关系建边,就转换成求一个最大独立集所包含的点数。
其实本身也就有这个定理:
最大团=原图补图的最大独立集

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define M 1009
int mp[M][M];
int g,b,m;
bool used[M];
int match[M];
void init()
{
    for(int i = 1;i <= g;i++)
    {
        for(int j = 1;j <= b;j++) mp[i][j] = 1;
    }
    //memset(mp,0,sizeof(mp));
}
bool dfs(int u)
{
    for(int i = 1; i <= b;i++)
    {
        if(mp[u][i] == 0) continue;
        int v = i;
        if(!used[v])
        {
            used[v] = true;
            if(match[v] == -1 || dfs(match[v]))
            {
                match[v] = u;
                return true;
            }
        }
    }
    return false;
}
int b_match()
{
    int ans = 0;
    memset(match,-1,sizeof(match));
    for(int i = 1;i <= g;i++)
    {
        memset(used,false,sizeof(used));
        if(dfs(i)) ans++;
    }
    return ans;
}
int main()
{
    int k = 0;
    while(scanf("%d %d %d",&g,&b,&m) == 3)
    {
        k++;
        init();
        if(g == 0 && b == 0 && m == 0) break;
        for(int i = 0; i < m;i++)
        {
            int u,v;
            scanf("%d %d",&u,&v);
            mp[u][v] = 0;
        }
        printf("Case %d: ",k);
        int ans = b_match();
        printf("%d\n",g+b-ans);
    }
    return 0;
}

你可能感兴趣的:(poj 3692 最大团(二分图匹配,最大独立集))