POJ - 3692 Kindergarten 二分图 最大匹配

来源:互联网 发布:知乎一句话 编辑:程序博客网 时间:2024/05/13 11:50

题目大意:给出n个男生,m个女生,还有k对男女认识关系,性别相同的人都相互认识。现在要求你挑出k个人,使得这k个人两两之间都相互认识

解题思路:要挑都认识的人,可以排除掉不认识的人。
可以分成两个点集,一个点集是男,一个点集是女,两个点集的连线表示两个人互不相认识,所以只要找到最大的互不相认识的匹配数,再用 n + m -互不相认识的匹配数,得到的人就是都相互认识的人了

#include<cstdio>#include<cstring>#include<vector>using namespace std;const int N = 210;int n, m, k;int vis[N], link[N], g[N][N];vector<int> r[N];void init() {    for(int i = 1; i <= n; i++)        r[i].clear();    memset(g, 0, sizeof(g));    int x, y;    for(int i = 0; i < k; i++) {        scanf("%d%d", &x, &y);        g[x][y] = 1;    }    for(int i = 1; i <= n; i++)        for(int j = 1; j <= m; j++)            if(!g[i][j])                r[i].push_back(j);    memset(link, 0, sizeof(link));}bool dfs(int u) {    for(int i = 0; i < r[u].size(); i++) {        if(vis[r[u][i]])            continue;        vis[r[u][i]] = 1;        if(!link[r[u][i]] || dfs(link[r[u][i]])) {            link[r[u][i]] = u;            return true;        }    }    return false;}void hungary() {    int ans = 0;    for(int i = 1; i <= n; i++) {        memset(vis, 0, sizeof(vis));        if(dfs(i))            ans++;    }    printf("%d\n", n + m - ans);}int main() {    int cas = 1;    while(scanf("%d%d%d", &n, &m, &k) != EOF && n + m + k) {        printf("Case %d: ", cas++);        init();        hungary();    }    return 0;}
0 0