Description
有 G G 个女孩和个男孩,男孩互相认识,女孩互相认识,一些男孩和一些女孩认识,现在要选出一些孩子做游戏,要求这些孩子互相认识,问至多可以选多少个孩子
Input
多组用例,每组用例输入三个整数 G,B,M G , B , M ,之后 M M 行每行输入两个整数表示 i i 男孩和女孩认识
(1≤G,B≤200,0≤M≤G×B) ( 1 ≤ G , B ≤ 200 , 0 ≤ M ≤ G × B )
Output
输出最多可以选出多少孩子做游戏
Sample Input
2 3 3
1 1
1 2
2 3
2 3 5
1 1
1 2
2 1
2 2
2 3
0 0 0
Sample Output
Case 1: 3
Case 2: 4
Solution
问题即为求该二分图的最大团,转化为求其补图的最大点独立集,而最大点独立集等于总点数 − − <script type="math/tex" id="MathJax-Element-9">-</script>最大匹配,故对其补图求最大匹配即可
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define maxn 555
int uN,vN; //u,v数目
int g[maxn][maxn];//编号是0~n-1的
int linker[maxn];
bool used[maxn];
bool dfs(int u)
{
int v;
for(v=0;v<vN;v++)
if(g[u][v]&&!used[v])
{
used[v]=true;
if(linker[v]==-1||dfs(linker[v]))
{
linker[v]=u;
return true;
}
}
return false;
}
int hungary()
{
int res=0;
int u;
memset(linker,-1,sizeof(linker));
for(u=0;u<uN;u++)
{
memset(used,0,sizeof(used));
if(dfs(u)) res++;
}
return res;
}
int main()
{
int G,B,M,res=1;
while(scanf("%d%d%d",&G,&B,&M),G||B||M)
{
for(int i=0;i<maxn;i++)
for(int j=0;j<maxn;j++)
g[i][j]=1;
uN=G;vN=B;
while(M--)
{
int x,y;
scanf("%d%d",&x,&y);
g[x-1][y-1]=0;
}
printf("Case %d: %d\n",res++,G+B-hungary());
}
return 0;
}