题意:一坨男孩和女孩,给你一些关系对,表示他们会谈恋爱,求一个最大的子集,令其中的男孩女孩不会谈恋爱。
类型:二分图 / 最大独立集 / 匈牙利
分析:题目是明显的二分图模型,但是输入没有指明那些是男孩/女孩。所以要拆点,把 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 } }