题目链接:
http://poj.org/problem?id=3692
题目大意:
幼儿园里边有N个男孩和M个女孩,所有男生之间都互相认识,所有女生之间也都相互认识。
还有k对关系,表示某个男孩和某个女孩认识。现在要选择一些学生组成一个集合,使得这个
集合中所有的人都认识,求这个集合中最多能有多少人。
思路:
建立二分图,图的一边为男生,另一边为女生。不能直接选取认识关系来建边,应该选取不认
识的人建边,也就是认识关系的补集作为边集。这样匹配的两个人都是不认识的,求出来的最
大匹配数就是最多有多少对人相互不认识。而最大独立集 = N + M - 最大匹配数,就求出了最
多能能多少个同学组成一个集合,使得集合中所有人都相互认识。
所以建图时,先将Map[][]初始化为1,认识的人赋值为0,然后求最大匹配数,从而得到最大独
立集。
AC代码:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; const int MAXN = 220; bool Map[MAXN][MAXN]; bool Mask[MAXN]; int NX,NY; int cx[MAXN],cy[MAXN]; int FindPath(int u) { for(int i = 1; i <= NY; ++i) { if(Map[u][i] && !Mask[i]) { Mask[i] = 1; if(cy[i] == -1 || FindPath(cy[i])) { cy[i] = u; cx[u] = i; return 1; } } } return 0; } int MaxMatch() { int res = 0; for(int i = 1; i <= NX; ++i) cx[i] = -1; for(int i = 1; i <= NY; ++i) cy[i] = -1; for(int i = 1; i <= NX; ++i) { if(cx[i] == -1) { for(int j = 1; j <= NY; ++j) Mask[j] = 0; res += FindPath(i); } } return res; } int main() { int M,u,v,kase = 0; while(~scanf("%d%d%d",&NX,&NY,&M) && (NX||NY||M)) { for(int i = 1; i <= NX; ++i) for(int j = 1; j <= NY; ++j) Map[i][j] = 1; for(int i = 1; i <= M; ++i) { scanf("%d%d",&u,&v); Map[u][v] = 0; } printf("Case %d: %d\n",++kase,NX+NY-MaxMatch()); } return 0; }