原题:http://acm.hdu.edu.cn/showproblem.php?pid=2458
题意:
给出女孩人数、男孩人数,以及m条关系;
下面m行,u — v,表示女孩u和男孩v相互认识;
并且,男孩们之间相互认识,女孩们之间也相互认识;
问最多有多少个人,他们相互之间都认识;
思路:
显然是求最大团;
最大团 = 补图的最大独立集;
最大独立集 = 顶点数 - 最大匹配;
所以最大团 = 顶点数 - 补图的最大匹配数;
#include<stdio.h>
#include<string.h>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn = 250;
int g, b, m;
bool used[maxn], link[maxn][maxn];
int match[maxn];
int cas = 0;
vector<int>G[maxn];
bool find(int x)
{
for(int i = 0;i<G[x].size();i++)
{
int k = G[x][i];
if(!used[k])
{
used[k] = true;
if(match[k] == 0 || find(match[k]))
{
match[k] = x;
return true;
}
}
}
return false;
}
int main()
{
while(scanf("%d%d%d", &g, &b, &m)!=EOF)
{
if(g == 0 && b == 0 && m == 0)
break;
memset(link, false, sizeof link);
memset(match, 0, sizeof match);
while(m--)
{
int u, v;
scanf("%d%d", &u, &v);
link[u][v] = true;
}
for(int i = 1;i<=g;i++)
{
G[i].clear();
for(int j = 1;j<=b;j++)
{
if(!link[i][j])
G[i].push_back(j);
}
}
int sum = 0;
for(int i = 1;i<=g;i++)
{
memset(used, false, sizeof used);
if(find(i))
sum++;
}
printf("Case %d: %d\n", ++cas, g+b-sum);
}
return 0;
}