AC代码:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 510,M = 100010;
int n1,n2,m;
int h[N],e[M],ne[M],idx;
int match[N];
bool st[N];
void add(int a,int b)
{
e[idx]=b;
ne[idx]=h[a];
h[a]=idx;
idx++;
}
bool find(int x)
{
for(int i=h[x];i!=-1;i=ne[i])
{
int j=e[i];
if(!st[j])
{
st[j]=true;
if(match[j]==0||find(match[j]))
{
match[j]=x;
return true;
}
}
}
return false;
}
int main()
{
memset(h,-1,sizeof h);
cin>>n1>>n2>>m;
while(m--)
{
int a,b;
cin>>a>>b;
add(a,b);
}
int res=0;
for(int i=1;i<=n1;i++)
{
memset(st,false,sizeof st);
if(find(i))res++;
}
cout<<res;
}
相关解释:
这里每遍历到新的一个点,在遍历这个点能连接他所能连接到的第一个点,有两种情况:
1.这个点已经心有所属,那么看看能不能让他心有所属的那个点妥协,又有两种情况:
<1>能妥协:
那么就让当前这个点连接他所能连接到的第一个点,另外一个放弃这个点,妥协然后和另外的点连接。
<2>不能妥协:
那就接着遍历他所能连接的第二个点(一直到他所能连接的第n个点),再继续最开始的过程,如果遍历刀到第k个点刚好可以让其他点妥协,那么就成功了。如果不可以,那就失败了,返回false。
2.这个点没有心有所属,那么直接连接这个点,然后返回true。
那么匈牙利算法为什么可以找到最大匹配呢,因为我们每次遍历到新的点,都假定它的优先级最高,其他点都必须向他妥协,那么如果其他点可以妥协,就让新的点(霸道总裁)连接这个可以连的点,那不就是比原来的图又多了一条边吗,这样不就会一直增加吗,所以可以找到最大匹配。
注意:
这里的st数组每次都要初始化一下,表示的意思就是在妥协的过程中,这个点有没有被霸道总裁给选了,因为你干不过霸道总裁,所以这里设置成true,表示你不能选这个点。所以每遍历到新一个点,就初始化一次,因为每次都要妥协,每次的霸道总裁都在点。妥协的过程就一直递归。