poj3692(二分图最大独立集)

36 阅读2分钟

题目大概意思为有G个女生和B个男生,每个男生都相互认识,每个女生也相互认识,部分男生与部分女生相互认识,求最大相互认识的点集

题目很简单,只用稍微转换一下思路即可,因为我们要以男生与女生来构建二分图,所以所有边都应该连接男生和女生,因此男生与男生和女生与女生之间不应该有边相连。
因此我们以两人互不相识为条件构建边,这样就能得到一个二分图。

然后因为两点之间没有线等于两人认识,所以我们求的 |最大互相认识的点集| = |最大独立集|
有公式 : |最大独立集| + |最小顶点覆盖| = |所有顶点集|
二分图中 |最小顶点覆盖| = |最大匹配|
所以 |最大互相认识的点集| = |最大独立集| = |所有顶点集| - |最小顶点覆盖| = |所有顶点集| - |最大匹配|
(一道基础题 )

#include <iostream>
#include <stdio.h>
#include <vector>
#include <string.h>
using namespace std;
vector<int> data[205];
bool ddd[205][205];
int match[205];
bool used[205];
void add_edge(int from, int to)
{
    data[from].push_back(to);
}
bool dfs(int v)
{
    used[v] = true;
    for(int i = 0; i < data[v].size(); i++)
    {
        int u = data[v][i], w = match[u];
        if(w < 0 || !used[w] && dfs(w))
        {
            match[u] = v;
            return true;
        }
    }
    return false;
}
int main()
{
    int flag = 1;
    while(1)
    {
        memset(ddd, false, sizeof(ddd));
        int G, B, M;
        scanf("%d %d %d", &G, &B, &M);
        if(G == 0 && B == 0 && M == 0)
        {
            break;
        }
        for(int i = 0; i < G; i++)
        {
            data[i].clear();
        }
        for(int i = 0; i < M; i++)
        {
            int from, to;
            scanf("%d %d", &from, &to);
            ddd[from-1][to-1] = true;
        }
        for(int i = 0; i < G; i++)
        {
            for(int j = 0; j < B; j++)
            {
                if(!ddd[i][j])
                {
                    add_edge(i, j);
                }
            }
        }
        memset(match, -1, sizeof(match));
        int res = 0;
        for(int i = 0; i < G; i++)
        {
            memset(used, 0, sizeof(used));
            if(dfs(i))
            {
                res++;
            }
        }
        printf("Case %d: %d\n", flag, G + B - res);
        flag++;
    }
}