题意:在幼儿园中,男孩们相互认识,女孩们相互认识。但男孩和女孩相互之间只有部分人认识。给出男女孩之间认识的关系。让你求出最多的一组人,使得这组人中每个人都相互认识。
思路:这个题是求二分图中最大团的大小。
我们可以知道:图的最大团 = 补图的最大独立集。
最小顶点覆盖+ 最大独立集 = V(顶点数)
同时在二分图中,最小顶点覆盖=最大匹配数。
所以我们建立二分图的补图后,求出最大匹配数,再用顶点数减去最大匹配数,就是最终的结果。
代码如下:
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int MAX = 220;
int from[MAX];
vector<int> G[MAX];
bool tmp[MAX][MAX];
bool used[MAX];
int g,b,m;
int x,y;
bool match(int u)
{
for(int i = 0, sz = G[u].size(); i < sz; ++i){
int v = G[u][i];
if(used[v]) continue;
used[v] = true;
if(from[v] == -1 || match(from[v])){
from[v] = u;
return true;
}
}
return false;
}
int Hungry(){
int tot = 0;
memset(from,-1,sizeof(from));
for(int i = 1; i <= g; ++i){
memset(used,0,sizeof(used));
if(match(i)) tot++;
}
return tot;
}
int main(void)
{
//freopen("input.txt","r",stdin);
int cas = 1;
while(scanf("%d %d %d", &g,&b,&m),g||b||m){
memset(tmp,0,sizeof(tmp));
for(int i = 0; i < m; ++i){
scanf("%d %d",&x,&y);
tmp[x][y] = true;
}
for(int i = 1; i <= g; ++i){
G[i].clear();
for(int j = 1; j <= b; ++j)
if(!tmp[i][j])
G[i].push_back(j);
}
/*for(int i = 1; i <= g; ++i)
for(int j = 0, sz = G[i].size(); j < sz; ++j)
printf("%d%c",G[i][j]," \n"[j == sz -1]);
puts("");*/
// printf("%d\n",Hungry());
printf("Case %d: %d\n",cas++,g + b - Hungry());
}
return 0;
}