HDOJ 1068 Girls and Boys(二分图匹配 + 镜像构图)

来源:互联网 发布:宋喆 知乎 编辑:程序博客网 时间:2024/06/07 16:17


点击打开链接


题意:题目给出了n个男女,编号为0~n-1,其中有男生也有女生。然后给出n组关系,把每一个人和与他(她)有缘分的人输入。现在要挑几个人出来,他们两两之间都不能有缘分,那么最多可以挑几个人出来?


这道题如果是男生女生混合起来,左边是0~n-1,右边也是,这样构图明显是错的,因为如果左边的一个男生1匹配了右边的一个女生2,那么左边那个女生2本应该是不能再继续匹配的。我们希望的构图,是左边只有男生编号,右边是女生编号,左边1匹配右边2,但要是把编号分开来,是很难做到的。现在可以假设,男生有n个,编号为0~n-1,放在左边,女生也有n个,编号为0~n-1放在右边,左边的1匹配了右边的2,左边的2匹配了右边的1,这样就相当于我们希望得到的二分图再加上了一个镜像的该二分图。原图和镜像图的最大匹配数应该是一样的,两者的和是res,那么其中一个就是res/2。


最大独立集:从二分图顶点集中取出一个子顶点集,使他们两两之间不连通。

最大独立集顶点数 = 二分图中顶点数 - 最大匹配数



#include<cstdio>#include<cstring>#include<string>#include<cmath>#include<iostream>#include<vector>#include<algorithm>#define N 500using namespace std;int g[N][N], link[N], used[N];int n, a, m, b, res;int dfs(int u){    for (int v = 0; v < n; v++)        if (g[u][v] && !used[v])        {            used[v] = 1;            if (link[v] == -1 || dfs(link[v]))            {                link[v] = u;                return  1;            }        }    return 0;}int main(){    while (~scanf("%d", &n))    {        memset(g, 0, sizeof(g));        for (int i = 0; i < n; i++)        {            scanf("%d: (%d)", &a, &m);            for (int j = 0; j < m; j++)            {                scanf("%d", &b);                g[a][b] = 1;            }        }        memset(link, -1, sizeof(link));        res = 0;        for (int i = 0; i < n; i++)        {            memset(used, 0, sizeof(used));            if (dfs(i)) res++;        }        printf("%d\n", n - res/2);    }    return 0;}

0 0