一开始以为是个贪心,结果WA了好多次,在网上查了这道题,发现应该用匈牙利算法解决这道题。
关于匈牙利算法的讲解见:
https://blog.youkuaiyun.com/lw277232240/article/details/72615522
或
https://blog.youkuaiyun.com/dark_scope/article/details/8880547
匈牙利算法的核心是寻找増广路,是一种用增广路径求二分图最大匹配的算法。如果找不到増广路了,说明已经达到最大匹配。
代码如下:
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
int match[505]; //match[i]表示与男生i匹配的女生的编号
bool map[505][505],visited[505]; //map表示匹配图,map[i,j]表示女生i对男生j有无兴趣,visited[i]表示男生i是否被访问过
bool find(int x,int n) //匈牙利算法模板 ,x表女生编号,n表男生个数
{
for(int i=1;i<=n;i++)
{
if(!visited[i]&&map[x][i]) //男生i还没被访问而且女生x对男生i有兴趣
{
visited[i]=1; //访问i
if(match[i]==-1||find(match[i],n)) //match]i]=-1表示男生i还未匹配,如果这位男生还未匹配,或者已经匹配了,
但原先与他匹配的女生,可以去和别的男生匹配,就把这个男生让给女生x(这是个递归的过程)
{
match[i]=x;
return true; //匹配成功
}
}
}
return false; //匹配失败
}
int main()
{
int K,M,N,i,j;
int sum,a,b,mi,flag;
while(~scanf("%d",&K)&&K)
{
scanf("%d%d",&M,&N);
for(i=0;i<=M;i++)
for(j=0;j<=N;j++)
map[i][j]=0;
memset(match,-1,sizeof(match));
for(i=1;i<=K;i++)
{
scanf("%d%d",&a,&b);
map[a][b]=1;
}
sum=0;
for(i=1;i<=M;i++)
{
for(j=1;j<=N;j++) visited[j]=0; //每次visited都要初始化,这样才能模拟出那个把某个男生让给另外一个女生的过程。
if(find(i,N)) sum++;
}
printf("%d\n",sum);
}
return 0;
}