匈牙利算法算法笔记

· · 算法·理论

匈牙利算法

其实我们可以看做一个月老在牵红线,现在左边是男生,右边是女生,互相都有心仪的对象,我们就要尽量每一个男生都好。然后就出现了一个图。

我们先看第一个男生,他有两个心仪的对象,先看第一个女生,还是单身,那就选第一个,然后看下一位,也是第一个单身,就她了。但是第三位男生就出问题了,他只有一位心仪的对象,但是呢,那位已经有对象了,但是这位男生还是不放弃,找到那个男朋友,说:“要不你换一换”。我们再一看,确实还有一个备胎单身,就换一个,这样两个人都好,最后一个也很正常,直接匹配。所以总结出十六字真言:待字闺中,据为己有;名花有主,求他放手。 所以说这也告诉我们不要轻易放弃,最后悔的不是做错,而是错过。

代码实践

#include<bits/stdc++.h>
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++;
}
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()
{
    scanf("%d%d%d",&n1,&n2,&m);
    memset(h,-1,sizeof h);
    while(m--)
    {
        int a, b;
        scanf("%d%d",&a,&b);
        add(a,b);
    }
    int res=0;
    for(int i=1;i<=n1;i++)
    {
        memset(st,false,sizeof(st));
        if(find(i))//开始相亲
            res++;
    }
    printf("%d\n",res);
    return 0;
}