Link:http://poj.org/problem?id=3692
Kindergarten
Description In a kindergarten, there are a lot of kids. All girls of the kids know each other and all boys also know each other. In addition to that, some girls and boys know each other. Now the teachers want to pick some kids to play a game, which need that all players know each other. You are to help to find maximum number of kids the teacher can pick. Input The input consists of multiple test cases. Each test case starts with a line containing three integers The last test case is followed by a line containing three zeros. Output For each test case, print a line containing the test case number( beginning with 1) followed by a integer which is the maximum number of kids the teacher can pick. 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 Source |
题意:给出男孩人数n,女孩人数m,男孩之间相互认识,女孩之间也相互认识,有s对男女相互认识。求最大的相互认识的人数。
编程思想:题目相当于给出一张二分图,求该二分图的最大团。而一般图的最大团是NP难题,但求二分图时我们可以转换为原图补图的最大独立集。因为:
最大团=原图补图的最大独立集
原图补图的最大独立集=原图补图的顶点数-原图补图的最大匹配边数
AC code:
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
#define maxm 405
int n,m,s;
int map[maxm][maxm],vis[maxm],link[maxm];//map存图
int dfs(int t)
{
for(int i=1;i<=m;i++)
{
if(vis[i]==0&&map[t][i])
{
vis[i]=1;
if(link[i]==-1||dfs(link[i]))
{
link[i]=t;
return 1;
}
}
}
return 0;
}
int MaxMatch()//匈牙利算法求最大匹配边数
{
int num=0;
memset(link,-1,sizeof(link));
for(int i=1;i<=n;i++)
{
memset(vis,0,sizeof(vis));
if(dfs(i))
num++;
}
return num;
}
/*
最大团=原图补图的最大独立集
原图补图的最大独立集=原图补图的顶点数-原图补图的最大匹配边数(二分图当然也成立)
*/
int main()
{
//freopen("D:\in.txt","r",stdin);
int a,b,cas=0;
while(~scanf("%d%d%d",&n,&m,&s))
{
if(n==0&&m==0&&s==0) break;
memset(map,0,sizeof(map));
for(int i=1; i<=s; i++)
{
cin>>a>>b;
map[a][b]=1;
}
for(int i=1;i<=n;i++)//求二分图的补图(还是二分图)
{
for(int j=1;j<=m;j++)
{
if(i!=j)
map[i][j]^=1;
else
map[i][j]=0;
}
}
cas++;
printf("Case %d: %d\n",cas,n+m-MaxMatch());
}
return 0;
}