匈牙利算法(二分图匹配问题)
问题链接(杭电2063题):http://acm.hdu.edu.cn/showproblem.php?pid=2063
参考博客:https://blog.csdn.net/cillyb/article/details/55511666
找伴侣是个递归的过程,最最关键的字就是“腾”字
其原则大概是:有机会上,没机会创造机会也要上
#include<iostream>
#include<cstring>
using namespace std;
/*匈牙利算法,二分图匹配,杭电2063题*/
int k,m,n; //k为组合数,m为左侧数,n为右侧点数
bool vis[520]; //这个右侧点是否被找过
int line[520][520];
//line表示左侧女生和右侧男生是否相互喜欢
int peidui[520];
//peidui表示右侧男生匹配到的左侧女生的点
bool find(int x) //匈牙利算法是递归的
{
for(int i=1;i<=n;i++) //遍历图的左侧所有男生
{
if(line[x][i]==1&&!vis[i]) //如果该右侧男生没有被访问过,并且左侧x喜欢右侧i
{
vis[i]=true; //设置该右侧男生被访问过
if(peidui[i]==0||find(peidui[i])) //如果右侧男生没有被配对,或者右侧的原配可以寻找到新的配对
{
peidui[i]=x; //则该右侧点匹配到该左侧点
return true; //返回结果真
}
}
}
return false; //否则返回结果假
}
int main()
{
int ans; //最大配对数
int g,b; //g为图的左侧,b为右侧
while(cin>>k&&k) //输入组合数
{
cin>>m>>n; //输入图左侧点的个数、图右侧点的个数
memset(line,0,sizeof(line)); //初始化邻接矩阵
memset(peidui,0,sizeof(peidui)); //初始化访问数组
for(int i=0;i<k;i++)
{
cin>>g>>b; //输入左侧点、右侧点
line[g][b]=1; //g左侧喜欢b右侧,设置为有边
}
ans=0;
for(int i=1;i<=m;i++) //遍历所有左侧点
{
memset(vis,false,sizeof(vis)); //每次都需要初始化访问数组
if(find(i)) ans++; //如果配对成功,结果自增
}
cout<<ans<<endl; //输出结果
}
}