题意:一坨男孩和女孩,给你一些关系对,表示他们会谈恋爱,求一个最大的子集,令其中的男孩女孩不会谈恋爱。
类型:二分图 / 最大独立集 / 匈牙利
分析:题目是明显的二分图模型,但是输入没有指明那些是男孩/女孩。所以要拆点,把 i 拆成 i 跟 i' 分别放入X、Y,构造二分图。原先U = V - M,所以 2U = 2V - 2M。
故U = n - M'/2。
反思:这题竟然改了5次才A [汗],具体哪些点都在注释中标出来了。。。
1、vis[]、flag[] 都是只要对应 v 的,G[][] 只用标出X-》Y即可。
2、flag 在 点的标号可以为0时,用-1做特殊值。
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<string>
using namespace std;
#define MAXN 2002 //题目没说
//int G[MAXN][MAXN+MAXN]; //④ 没必要这样建,竟然MLE。。。。
int G[MAXN][MAXN];
int n; // 点编号 0~n-1、n~2n-1
int vis[MAXN], flag[MAXN]; //④vis 跟 flag 对应的 只需要是 v,所以可以MAXN
int dfs(int u)
{
for(int v=0; v<n; v++) if(G[u][v])
{
if(!vis[v])
{
vis[v] = 1;
if(flag[v]==-1 || dfs(flag[v]))
{
flag[v] = u;
return 1;
}
}
}
return 0;
}
int read_graph()
{
memset(G, 0, sizeof(G)); //① 竟然忘了清图
if(cin>>n)
{
for(int i=0; i<n; i++) //0: (3) 4 5 6
{
char junk;
int u, t;
cin>>u>>junk>>junk>>t>>junk; //⑤ 我原来用string为什么RE (ACCESS_VIOLATION)????
// cin>>junk>>buf;
// int u = junk[0]-'0'; //③ 题目输入u不一定按顺序
// int t = buf[1]-'0';
while(t--)
{
int v; cin>>v;
G[u][v] = 1;
}
}
return 1;
}
else
return 0;
}
int main()
{
while(read_graph())
{
int cnt=0;
memset(flag, -1, sizeof(flag)); //② 标号可能为0,flag要以-1作为特殊值
for(int i=0; i<n; i++)
{
memset(vis, 0, sizeof(vis));
if(dfs(i))
{
cnt++;
}
}
cout<<n - cnt/2<<endl; //U = V - M
// U= V - M'/2
}
}