给定一张二分图,其左部点集大小为 n,右部点集大小为 m,请求出其最大匹配。
对于以上问题,匈牙利算法给出的解决方案为,对于每个节点u,先匹配它第一条边,若对应的v还没被匹配,就可以顺理成章的将u、v匹配上,进行下一个u的匹配;若此时的v已经被之前的u'匹配上了,那么就看u'能否有其他的选择,如果有就可以让u'退让,连v',然后u就可以连v了;如果u'没有其他选择,那就不让,使得u没有对应的匹配
大概的思路就是这样
其实也可以用网络流解决,将左部的节点连一个超级源点,右部的点全部连一个超级汇点,左部右部之间正常建边,将这些边的边权全部赋为1,然后dinic解决即可
匈牙利算法代码
#include<bits/stdc++.h>
using namespace std;
vector <int> G[1005];
int t,n,m,vis[1005],mat[1005];
bool dfs(int u)
{
if(vis[u]==1) return false;
vis[u]=1;
for(int k=0;k<G[u].size();k++)
if(mat[G[u][k]]==0 || dfs(mat[G[u][k]]))
{
mat[G[u][k]]=u;
return true;
}
return false;
}
int main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
scanf("%d%d%d",&n,&m,&t);
int x,y;
for(int i=1;i<=t;i++)
scanf("%d%d",&x,&y),G[x].push_back(y);
int ans=0;
for(int i=1;i<=n;i++)
{
if(dfs(i)) ans++;
memset(vis,0,sizeof(vis));
}
printf("%d\n",ans);
return 0;
}
注意这个vis数组要每次清零