算法学习笔记(5):匈牙利算法

天天见闻 天天见闻 2022-12-18 综合 阅读: 118
摘要: 匈牙利算法主要用于解决一些与二分图匹配有关的问题,所以我们先来了解一下二分图。匈牙利算法主要用来解决两个问题:求二分图的最大匹配数和最小点覆盖数。现在我们来看看匈牙利算法是怎么运作的:这就是匈牙利算法的流程,至于具体实现,我们来看看代码:这为什么用匈牙利算法可以解决呢?匈牙利算法的应用一些题目,乍一看与上面这个男女配对的问题没有任何相似点,其实都可以用匈牙利算法。所以直接套匈牙利算法即可。

今天我们来看一个没有前几篇讲的那么常用,但是很有用的算法:匈牙利算法( )。匈牙利算法主要用于解决一些与二分图匹配有关的问题,所以我们先来了解一下二分图。

二分图( graph)是一类特殊的图,它可以被划分为两个部分,每个部分内的点互不相连。下图是典型的二分图。

鱼群算法跟粒子群算法_算法_银行家算法 安全性算法

一张二分图

可以看到,在上面的二分图中算法,每条边的端点都分别处于点集X和Y中。匈牙利算法主要用来解决两个问题:求二分图的最大匹配数和最小点覆盖数。

这么说起来过于抽象了,我们现在从实际问题出发。

最大匹配问题

看完上面讲的,相信读者会觉得云里雾里的:这是啥?这有啥用?所以我们把这张二分图稍微做点手脚算法,变成下面这样:

鱼群算法跟粒子群算法_算法_银行家算法 安全性算法

现在Boys和Girls分别是两个点集,里面的点分别是男生和女生,边表示他们之间存在“暧昧关系"。最大匹配问题相当于,假如你是红娘,可以撮合任何一对有暧昧关系的男女,那么你最多能成全多少对情侣?(数学表述:在二分图中最多能找到多少条没有公共端点的边)

现在我们来看看匈牙利算法是怎么运作的:

我们从B1看起(男女平等,从女生这边看起也是可以的),他与G2有暧昧,那我们就先暂时把他与G2连接(注意这时只是你作为一个红娘在纸上构想,你没有真正行动,此时的安排都是暂时的)。

银行家算法 安全性算法_鱼群算法跟粒子群算法_算法

来看B2,B2也喜欢G2,这时G2已经“名花有主”了(虽然只是我们设想的),那怎么办呢?我们倒回去看G2目前被安排的男友,是B1,B1有没有别的选项呢?有,G4,G4还没有被安排,那我们就给B1安排上G4。

算法_鱼群算法跟粒子群算法_银行家算法 安全性算法

然后B3,B3直接配上G1就好了,这没什么问题。至于B4,他只钟情于G4,G4目前配的是B1。B1除了G4还可以选G2,但是呢,如果B1选了G2,G2的原配B2就没得选了。我们绕了一大圈,发现B4只能注定单身了,可怜。(其实从来没被考虑过的G3更可怜)

银行家算法 安全性算法_鱼群算法跟粒子群算法_算法

这就是匈牙利算法的流程,至于具体实现,我们来看看代码:

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

其实流程跟我们上面描述的是一致的。注意这里使用了一个递归的技巧,我们不断往下递归,尝试寻找合适的匹配。

最小点覆盖问题

另外一个关于二分图的问题是求最小点覆盖:我们想找到最少的一些点,使二分图所有的边都至少有一个端点在这些点之中。倒过来说就是,删除包含这些点的边,可以删掉所有边。

算法_鱼群算法跟粒子群算法_银行家算法 安全性算法

这为什么用匈牙利算法可以解决呢?你如果以为我要长篇大论很久就错了,我们只需要一个定理:

(König定理)

一个二分图中的最大匹配数等于这个图中的最小点覆盖数。

好了,本节可以结束了,我们不是搞数学的,不需要证明(有兴趣的话可以参考这篇博客,虽然愚昧的我并没看懂)。但是提供一个直观地找最小覆盖点集的方法:看上节最后一张图(或题图),从左侧一个未匹配成功的点出发,走一趟匈牙利算法的流程(即紫色的箭头),所有左侧未经过的点,和右侧经过的点,即组成最小点覆盖。(即图中的B3、G2、G4)

匈牙利算法的应用

一些题目,乍一看与上面这个男女配对的问题没有任何相似点,其实都可以用匈牙利算法。例如:

(洛谷P1129) []矩阵游戏

题目描述

小Q是一个非常聪明的孩子,除了国际象棋,他还很喜欢玩一个电脑益智游戏――矩阵游戏。矩阵游戏在一个 N \times N 黑白方阵进行(如同国际象棋一般,只是颜色是随意的)。每次可以对该矩阵进行两种操作:

行交换操作:选择矩阵的任意两行,交换这两行(即交换对应格子的颜色)

列交换操作:选择矩阵的任意两列,交换这两列(即交换对应格子的颜色)

游戏的目标,即通过若干次操作,使得方阵的主对角线(左上角到右下角的连线)上的格子均为黑色。

对于某些关卡,小Q百思不得其解,以致他开始怀疑这些关卡是不是根本就是无解的!于是小Q决定写一个程序来判断这些关卡是否有解。

输入格式

第一行包含一个整数T,表示数据的组数。

接下来包含T组数据,每组数据第一行为一个整数N,表示方阵的大小;接下来N行为一个N \times N的01矩阵(0表示白色,1表示黑色)。

输出格式

包含T行。对于每一组数据,如果该关卡有解,输出一行Yes;否则输出一行No。

我们把矩阵转化为二分图(左侧集合代表各行,右侧集合代表各列,某位置为1则该行和该列之间有边)。我们想进行一系列交换操作,使得X1连上Y1,X2连上Y2,……

大家可以想象,所谓的交换,是不是可以等价为重命名?我们可以在保持当前二分图结构不变的情况下,把右侧点的编号进行改变,这与交换的效果是一样的。

银行家算法 安全性算法_鱼群算法跟粒子群算法_算法

所以想让X1、X2...与Y1、Y2...一一对应,其实只需要原图最大匹配数为4就行了。(这与组合数学中相异代表系的概念相合)。代码如下:

#include 
#include 
int Map[205][205], p[205], vis[205], N, T;
bool match(int i)
{
    for (int j = 1; j <= N; ++j)
    {
        if (Map[i][j] && !vis[j])
        {
            vis[j] = 1;
            if (p[j] == 0 || match(p[j]))
            {
                p[j] = i;
                return true;
            }
        }
    }
    return false;

}
int Hungarian()
{
    int cnt = 0;
    for (int i = 1; i <= N; ++i)
    {
        memset(vis, 0, sizeof(vis));
        if (match(i))
            cnt++;
    }
    return cnt;
}
int main()
{
    scanf("%d", &T);
    while (T--)
    {
        scanf("%d", &N);
        memset(p, 0, sizeof(p));
        for (int i = 1; i <= N; ++i)
            for (int j = 1; j <= N; ++j)
                scanf("%d", &Map[i][j]);
        puts(Hungarian() == N ? "Yes" : "No");

    }
    return 0;
}

() CoVH之柯南开锁

面对OIBH组织的嚣张气焰, 柯南决定深入牛棚, 一探虚实.

他经过深思熟虑, 决定从OIBH组织大门进入...........

OIBH组织的大门有一个很神奇的锁.

锁是由M*N个格子组成, 其中某些格子凸起(灰色的格子). 每一次操作可以把某一行或某一列的格子给按下去.

鱼群算法跟粒子群算法_算法_银行家算法 安全性算法

如果柯南能在组织限定的次数内将所有格子都按下去, 那么他就能够进入总部. 但是OIBH组织不是吃素的, 他们的限定次数恰是最少次数.

请您帮助柯南计算出开给定的锁所需的最少次数.

读入/Input:

第一行 两个不超过100的正整数N, M表示矩阵的长和宽

以下N行 每行M个数 非0即1 1为凸起方格

输出/:

一个整数 所需最少次数

如果我们把样例的矩阵,转化为二分图的形式,是这样的:

鱼群算法跟粒子群算法_算法_银行家算法 安全性算法

按下一行或一列,其实就是删掉与某个点相连的所有边。现在要求最少的操作次数,想想看,这不就是求最小点覆盖数吗?所以直接套匈牙利算法即可。代码略。

(TYVJ P1035) 棋盘覆盖

描述

给出一张n*n(n

其他相关

超级项目经理应该掌握的99种武器之6:波士顿矩阵

作者: 天天见闻 时间:2024-04-02 阅读: 1
波士顿矩阵将业务类型分为四种:波士顿矩阵的优点是简单明了,可以使集团在资源有限的情况下,合理安排产品系列组合,收获或放弃萎缩产品,加大在更有发展前景的产品上投资。波士顿矩阵与项目管理:在进行项目组合管理的时候,波士顿矩阵是很好的战略分析和选择工具。...

图解 transformer——多头注意力

作者: 天天见闻 时间:2024-04-02 阅读: 1
各注意力头没有单独的线性层,而是所有的注意力头共用线性层,只是不同的注意力头在独属于各自的逻辑部分上进行操作。这使得计算更加有效,同时保持模型的简单:所需线性层更少,同时获得了多头注意力的效果。中,一个注意力头的完整注意力计算如下图所示:整体上多头注意力的计算过程如下:...
西麦科技申请基于人工智能算法的室内地图自动识别绘制方法及装置专利,提升地图绘制效率

西麦科技申请基于人工智能算法的室内地图自动识别绘制方法及装置专利,提升地图绘制效率

作者: 天天见闻 时间:2024-04-01 阅读: 1
金融界2024年3月30日消息,据国家知识产权局公告,广州西麦科技股份有限公司申请一项名为“基于人工智能算法的室内地图自动识别绘制方法及装置“,公开号CN117782061A,申请日期为2023年12月。 专利摘要显示,本发明提出了一种基于人工智能算法的室内地图自动识别绘制方法及装置,所述方法包括:基于室内空间布置基准定位设备,并确定关键位置坐标;获取关键位置坐标相对于各所述基准定位设备的固有信号参数;基于固有信号参数获取各关键位置坐标处的图像,以及图像中各关键标识元素的特征参数;基于各关键位置坐标、各关键位置坐标处的图像及对应图像中关键识别元素的特征参数,根据预设算法绘制室内地图。所述装置用于实现所述方法。本发明可以实现室内地图的自动识别和绘制,提升了地图绘制效率。...
C++求直线方程并求直线延长线上的某点的算法

C++求直线方程并求直线延长线上的某点的算法

作者: 天天见闻 时间:2024-03-03 阅读: 32
3:截距式:x/a+y/b=1【适用于不过原点或不垂直于x轴、y轴的直线】5:两点式:【适用于不垂直于x轴、y轴的直线】直线方程求解是一个相对简单的过程,使用的是斜截式方程,先考虑特殊情况,在用斜截式的方法替换就行,pt1和pt2为起点,nLen为延长的距离可为负数,Outpt为计算的延长的点。...

Win10玩游戏卡怎么办 玩游戏卡顿解决办法详细教程

作者: 天天见闻 时间:2023-11-23 阅读: 64
但是有些玩家有卡尔顿的现象,今天为您送上解决方案。Win10如何玩游戏卡Win10游戏卡解决方案Win10的游戏模式有两个作用,一是在游戏时阻止更新,防止系统卡;二是分配更多的CPU和GPU资源,保留无关的进程。这是一个小工具的玩家,可以帮助N卡用户优化游戏设置。...
苹果合作研发突破性算法,可从动态 RGB 图像中实时重建 3D 图像

苹果合作研发突破性算法,可从动态 RGB 图像中实时重建 3D 图像

作者: 天天见闻 时间:2023-11-18 阅读: 45
据IT之家11月2日消息,苹果公司近日与加州大学圣芭芭拉分校的研究人员共同演示并介绍了一种划时代的算法,可以从视频RGB图像在线重构3D图像。 双方团队将挑战低纹理区域,尝试解决重构图像固有的模糊性,将目光投向实时执行的实用解决方案,未来将引入智能手机等移动设备。 新算法根据历史当前观测结果生成准确的增量重构,解决了同步定位和地图映射(SLAM)系统的动态特性,确保了与SLAM更新的一致。 以前在密集的纯RGB重构中,极大地忽略了在线应用中相机姿态估计的动态特性,在重构过程中仍然采用静态输入图像的传统表现。...
我来说两句

年度爆文