您的位置:首页 > 其它

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

2016-03-06 10:24 465 查看
点击打开链接

题意:题目给出了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 500
using namespace std;
int g

, link
, used
;
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: