原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=2063
题意:
m个女生和n个男生去坐过山车,每个女生有自己想要搭配的男生(0个或者多个),一个女生最多和一个男生搭配,只有搭配成功的男女可以去坐过山车,求最多可以有多少对男女可以坐上过山车。
题解:
二分图匹配裸题。
利用数组记录图上边的关系,对于每个女生遍历每个男生,若是这个男生和女生之间有边,且这个男生没有被别的女生配对,那么这两个人配对,如果这个男生已经配对过,那么向前递归该男生匹配的女生girl【i】,如果还有可以匹配的男生,那么放弃掉这个男生,换下一个男生。对于girl【i】的匹配与之前相同。
原则:
后来者居上,如果后来的人和前面的人可以匹配同一人,并且前面的人还可以匹配别的人,那么前面的人就要将自己之前的匹配对象让给后来的人,前面的人更换匹配对象,继续向前递归。
AC代码:
#include <bits/stdc++.h>
//#pragma GCC optimize(2)
using namespace std;
#define LL long long
#define Rint register int
#define U unsigned
#define forn(i,a,b) for(int i = a;i <= b;++i)
#define nfor(i,a,b) for(int i = a;i >= b;--i)
#define pii pair<int ,int>
#define MS0(X) memset(X,0,sizeof(X))
#define MSf(X) memset(X,false,sizeof(X))
#define MS1(X) memset(X,-1,sizeof(X))
#define BR printf("--------------------\n")
#define pb push_back
#define rep(i,a,b) for(Rint i=a;i<=b;++i)
#define DEBUG(x) std::cerr << #x << '=' << x << std::endl
const int maxn=505;
int n,k,m;
int mp[maxn][maxn];//记录女i和男j是否有边
int vis[maxn],girl[maxn];
int find_(int x)
{
for(int i=1;i<=n;i++)
{
if(mp[x][i]==1&&!vis[i])
{
vis[i]=1;//标记此男生已被匹配
if(girl[i]==0||find_(girl[i]))//第i个男生没被匹配过或者,之前匹配该男生的女生还可以匹配到别的女生
{
girl[i]=x;
return 1;//新增加了一个匹配
}
}
}
return 0;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
while(cin>>k)
{
if(k==0)break;
MS0(mp);
MS0(girl);
cin>>m>>n;
for(int i=0;i<k;i++)
{
int u,v;
cin>>u>>v;
mp[u][v]=1;
}
int ans=0;
for(int i=1;i<=m;i++)
{
MS0(vis);
if(find_(i))
ans++;
}
cout<<ans<<"\n";
}
return 0;
}
欢迎评论!