匈牙利算法


前言

复习acwing算法基础课的内容,本篇为讲解基础算法:匈牙利算法,关于时间复杂度:目前博主不太会计算,先鸽了,日后一定补上。


一、匈牙利算法

下图来自:ACWing算法基础课

在这里插入图片描述

匈牙利算法是用来寻找二分图最大匹配的算法具体实现方式下面做讲解:
我们把两个集合分为男,女两个集合,其中的每一条黑线都意味着这一对儿男女之间有感情,我们要做的,是看看能最多有多少对男女能够实现配对,下面我们一步一步看:
在这里插入图片描述

我们遍历每一个男生,那么一号男嘉宾和二号女嘉宾之间有一条线,证明他俩可成,我们标注一下
在这里插入图片描述

显然我们不能脚踏两条船,第一个男生已经心有所属,所以我们来看第二个男生,发现二号男嘉宾可以与一号女嘉宾实现配对,我们同样标记一下,代表他俩在一起了
在这里插入图片描述
接着,看到三号男嘉宾只喜欢二号女嘉宾,没有其他的选项了,那么我们把他们连一条线
在这里插入图片描述
尴尬的情况发生了,我们的二号女嘉宾居然脚踏两条船!!!,显然社会上不允许这样,那么二号女嘉宾就甩掉了一号男嘉宾
在这里插入图片描述
但是,一号男嘉宾也不是没有准备,一号男嘉宾还有一位“备胎”,四号女嘉宾,所以被甩了之后,就找上了四号女嘉宾
在这里插入图片描述
那么最后来看我们的四号男嘉宾,四号男嘉宾和三号女嘉宾之间有感情,同样上述操作
在这里插入图片描述
至此,所有的男女嘉宾都找到了自己的心上人,匈牙利算法结束


二、AcWing 861. 二分图的最大匹配

本题链接:AcWing 861. 二分图的最大匹配
本博客给出本题截图:

在这里插入图片描述
在这里插入图片描述

本题分析

注意本题是无向图,但是根据我们上述的对匈牙利算法实现的讲解中可以看出来,其实我们只需要当成有向图去做就好了,即当成男追女,而不是双向奔赴.
match数组代表的含义就是找对象,match[i] = j;的意思就是女朋友i的男朋友为j,match[j] == 0意味着没有男朋友
st数组的含义是是否被选定了,st[i] == false意味着i这个女嘉宾没有被其他男嘉宾选定

if (match[j] == 0 || find(match[j]))
{
	match[j] = x;
	return true;
}

这里的意思是如果j号女嘉宾没有男嘉宾,或者j号女嘉宾现在的对象有备胎,那么就让j号女嘉宾成为x号男嘉宾的对象

for (int i = 1; i <= n1; i ++ )
{
	memset(st, false, sizeof st);
	if (find(i)) res ++ ;
}

每一个男嘉宾开始寻找女嘉宾的时候,都是默认女嘉宾没有对象的,因为有对象就抢

AC代码

#include <cstring>
#include <cstdio>
#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 ++ ;
}

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;
}

三、时间复杂度

关于匈牙利算法的时间复杂度以及证明,后续会给出详细的说明以及证明过程,目前先鸽了。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

辰chen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值