匈牙利(Hungarian)算法-二分图的最大匹配问题
上述视频涉及到的一个打卡题目杭电OJ-2063-过山车
我的代码如下:(下面的代码同视频里的稍有不同,或者说是男女正好相反吧)
#include<bits/stdc++.h>
using namespace std;
const int maxn = 505;
int dict[maxn][maxn];
int vis[maxn];
int nxt[maxn];//某个男生有没有女生
int k,m,n;//m女生,n男生
bool match(int x)
{
for(int i=1;i<=n;i++)//遍历每个男生
{
if(dict[x][i] && !vis[i])//如果x女生对男生有意向且该男生还没有被访问过
{
vis[i]=1;//该男生在该女生的匹配阶段已经被访问过
if(nxt[i]==0 || match(nxt[i]))//如果男生没有被配对或者该男生配对的女生可以变换
{
nxt[i]=x;
return true;
}
}
}
return false;
}
int solve()
{
int sum = 0;
for(int i = 1;i<=m;i++)//遍历每个女生
{
memset(vis,0,sizeof(vis));
if(match(i))sum++;
}
return sum;
}
int main()
{
while(cin>>k && k)
{
//读入数据
memset(dict,0,sizeof(dict));
cin>>m>>n;
for(int i=0;i<k;i++)
{
int g,b;
cin>>g>>b;
dict[g][b]=1;
}
//初始化
memset(nxt,0,sizeof(nxt));
//解决问题
cout<<solve()<<endl;
}
return 0;
}
其实,上面那个视频并没有过多的涉及到匈牙利算法的内容,
也没有很好的讲明白递归算法的实现。
不过,这至少让你对匈牙利算法的大致思想有所了解。
下面,将会详细说明匈牙利算法及其前置概念。
接下来是一个CSDN的博文。
这个博客完全没有代码,但是它十分清晰的讲解了匈牙利算法算法精髓。
注意算法关键词:二部图(二分图)、增广路、递归、后来者居上
结合上面的解释以及打卡题目的代码,我们可以基本得到一个模板:
const int MAXN = 500;
int M, N; //M, N分别表示左、右侧集合的元素数量
int Map[MAXM][MAXN]; //邻接矩阵存图
int p[MAXN]; //记录当前右侧元素所对应的左侧元素
bool vis[MAXN]; //记录右侧元素是否已被访问过
bool match(int i)
{
for (int j = 1; j <= N; ++j)
if (Map[i][j] && !vis[j]) //有边且未访问
{
vis[j] = true; //记录状态为访问过
if (p[j] == 0 || match(p[j])) //如果暂无匹配,或者原来匹配的左侧元素可以找到新的匹配
{
p[j] = i; //当前左侧元素成为当前右侧元素的新匹配
return true; //返回匹配成功
}
}
return false; //循环结束,仍未找到匹配,返回匹配失败
}
int Hungarian()
{
int cnt = 0;
for (int i = 1; i <= M; ++i)
{
memset(vis, 0, sizeof(vis)); //重置vis数组
if (match(i))
cnt++;
}
return cnt;
}
OK