匈牙利算法详解

news2024/11/26 4:49:04

匈牙利算法(Hungarian Algorithm)是一种组合优化算法(combinatorial optimization algorithm),用于求解指派问题(assignment problem),算法时间复杂度为O(N^3)。Harold Kuhn发表于1955年,由于该算法基于两位匈牙利数学家的早期研究成果,所以被称作“匈牙利算法”。

假设有三位工人A,B和C,需要分配他们每人完成一件工作;对于不同的工作他们所需要花费的时间不同,如下表所示。问题就是要找到一套耗时最小的指派方案。用矩阵表示如下:
在这里插入图片描述

匈牙利算法包含四步。前两步一次执行完,第三步和第三步会重复执行直到最优分配出现。算法的输入是n*n的矩阵,只有非负数。
Step 1: Subtract row minima (减去行最小值)
对于每一行,找到该行的最小值,然后该行的数都减去这个最小值
Step 2: Subtract column minima(减去列最小值)
同样的,对于每一列,找到该列的最小值,然后该列的数都减去这个最小值

Step 3: Cover all zeros with a minimum number of lines(用最少的线覆盖所有的0)
用最少的水平线和垂直线覆盖掉矩阵的所有0元素。如果需要n条线,那么在这些0中就存在最优解。算法结束
如果需要的线<n,继续第四步
Step 4: Create additional zeros(创建额外的0元素)
在第三步的的矩阵中,找到没被线覆盖的行列中的最小的元素,记作k。所有没被覆盖的元素都减去k,被覆盖两次的元素加上k。

第一步,找出每一行中值最小的元素,然后把该行所有元素都减去这一最小值:

在这里插入图片描述
第二步,对于每一列,找到该列的最小值,然后该列的数都减去这个最小值
在这里插入图片描述
第三步,用最少的水平线和垂直线覆盖掉矩阵的所有0元素。如果需要n条线,那么在这些0中就存在最优解。算法结束
在这里插入图片描述
可以看到当前的覆盖所有的0需要两条线,<n,继续第四步

第四步,找到没被线覆盖的行列中的最小的元素,记作k。所有没被覆盖的元素都减去k,被覆盖两次的元素加上k
在这里插入图片描述此时刚好用3条线即可覆盖所有的0,算法结束
在这里插入图片描述

即最后指派A拖地,B擦桌,C扫厕所

二分图

1、一定不含有奇数环,可能包含长度为偶数的环, 不一定是连通图
2、二分图是图论中的一种特殊模型。设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图。简单来说,如果图中点可以被分为两组,并且使得所有边都跨越组的边界,则这就是一个二分图。准确地说:把一个图的顶点划分为两个不相交子集 ,使得每一条边都分别连接两个集合中的顶点。如果存在这样的划分,则此图为一个二分图,如下图所示的全都是二分图:
在这里插入图片描述

2.二分图的匹配

二分图的匹配:给定一个二分图 G,在 G 的一个子图 M 中,M 的边集 {E} 中的任意两条边都不依附于同一个顶点,则称 M 是一个匹配。
二分图的最大匹配:所有匹配中包含边数最多的一组匹配被称为二分图的最大匹配,其边数即为最大匹配数。
假设二分图的左边全为男生,右边全为女生,线连着的男女生为情侣关系,允许出现脚踏n条船等混乱的男女关系的情况,那么:

二分图的匹配:把二分图删除一些边使男女生之间的关系没有出现脚踏n条船的情况,就说删除边后得到的新图为一个匹配(允许出现单身狗的情况)
二分图的最大匹配:删除部分边使得保留的情侣数量最多,我们就称这个匹配为最大匹配。
比如在上面的4张图中,图1就是图3的一个最大匹配。

3、匈牙利算法的实现步骤

有如下图:

在这里插入图片描述
1.情况一(你是我的唯一)
首先我们看向男1,发现男1很纯情的只喜欢着女2,那么就成全他们吧。确定他们两个人的情侣关系。
在这里插入图片描述
2.情况二(你们都是我的翅膀)
接下来我们看向男2,发现男2喜欢着女1和女3两个女孩子。问问男2吧,他表示:我对这两个女孩子都是真心的,选谁都行!

选谁都行啊,那我们就随便选吧,把男2和女1牵上红线。
在这里插入图片描述
3.情况三(我会把你抢过来)
搞定,然后我们再看看男3,男3表示:我也喜欢女1啊!明明是我更加喜欢她!为什么?为什么她和别人在一起了啊!我不能接受!
嗯…看来我们的男3不想放弃啊,那我们尝试和男2交涉一下。
“男2呀,你有备胎吗?”
“有啊,怎么了?”
“男3看上了你女朋友,要不你和你备胎在一起,把你女朋友让给别人吧”
“嗯…好吧,记得让他请我吃饭”(作者对男2这种渣男表示强烈谴责!)
ok,这样的话事情就圆满解决了,可喜可贺可喜可贺。
在这里插入图片描述

4.情况四(我爱的人已经有了爱人)
解决了男2和男3的问题,我们再看向男4。

男4说:我喜欢女3!我想和女3在一起!
我看了看,女3不是男2的新女友吗?额…我再去找男2看看吧。

“什么?还要我换?大哥,我没别的备胎了,我拒绝!要是我还有备胎的话还差不多。”(作者对男2这种渣男表示强烈谴责!)

我们只好回头土脸的找到男4。那个,我们交涉失败了,女3是没戏了,要不你换一个追求对象我帮你争取一下?

男4低头沉思了一下,“我觉得吧,女4其实也挺可爱的。”

ok,安排!我们看了看,发现女4还是单身呢,那就成全你们吧。
在这里插入图片描述
最后,我们得到的最大匹配就是这样
在这里插入图片描述
总结:算法描述:
如果你想找的妹子已经有了男朋友,
你就去问问她男朋友,
你有没有备胎,
有备胎就把你女朋友让给我
你没有备胎我就只好找我的备胎
出处:1
2

代码:

在这里插入图片描述

#include <iostream>
#include <vector>

using namespace std;

// 使用DFS查找增广路径
bool dfs(vector<vector<int>>& graph, int u, vector<bool>& visited, vector<int>& match) {
    int m = graph.size();
    int n = graph[0].size();

    for (int v = 0; v < n; ++v) {
        if (graph[u][v] && !visited[v]) {
            visited[v] = true;

            // 如果v没有匹配或者可以找到增广路径
            if (match[v] == -1 || dfs(graph, match[v], visited, match)) {
                match[v] = u;
                return true;
            }
        }
    }

    return false;
}

// 计算二分图的最大匹配数
int hungarian(vector<vector<int>>& graph) {
    int m = graph.size();
    int n = graph[0].size();

    vector<int> match(n, -1); // 存储匹配信息,match[i]表示右侧第i个节点的匹配节点编号

    int count = 0; // 最大匹配数

    for (int u = 0; u < m; ++u) {
        vector<bool> visited(n, false); // 记录每个节点的访问状态

        if (dfs(graph, u, visited, match)) {
            count++;
        }
    }

    return count;
}

// 测试
int main() {
    vector<vector<int>> graph = {
        {1, 0, 1, 0},
        {1, 0, 0, 0},
        {0, 1, 1, 1},
        {0, 0, 1, 0}
    };

    int maxMatching = hungarian(graph);
    cout << "Maximum matching: " << maxMatching << endl;

    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/848065.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数字IC流片经历有多重要?怎样才能有流片机会?

都说拥有流片经验可以显示你在实际项目中的实践能力和对整个设计流程的了解程度&#xff0c;流片经历的重要性不言而喻。 什么是芯片流片 像流水线一样通过一系列工艺步骤制造芯片&#xff0c;这就是流片。在芯片制造过程中一般有两段时间可以叫作流片。 流片&#xff1a;英…

分布式测试插件 pytest-xdist 使用详解

目录 使用背景&#xff1a; 使用前提&#xff1a; 使用快速入门&#xff1a; 使用小结&#xff1a; 使用背景&#xff1a; 大型测试套件&#xff1a;当你的测试套件非常庞大&#xff0c;包含了大量的测试用例时&#xff0c;pytest-xdist可以通过并行执行来加速整体的测试过…

Unity数字可视化学校_昼夜(二)

1、时间设置&#xff1a; 2、新建夜晚 3、新建侧置球&#xff08;BOX&#xff09;,测试灯光强度 降低亮度 色调&#xff1a;冷色调 4、自发光 新建shader 灯光控制 道路线&#xff1a; 建筑&#xff1a; 夜晚加灯光&#xff1a; 玻璃&#xff1a; 加大灯光数量&#xff1a; 边缘…

深入理解负载均衡原理及算法

1. 前言 在互联网早期,网络还不是很发达,上网用户少,流量相对较小,系统架构以单体架构为主。但如今在互联网发达的今天,流量请求动辄百亿、甚至上千亿,单台服务器或者实例已完全不能满足需求,这就有了集群。不论是为了实现高可用还是高性能,都需要用到多台机器来扩展服…

校对软件助力司法公正:确保法律文书准确无误

校对软件在司法系统中的应用可以助力司法公正&#xff0c;确保法律文书的准确性和无误性。以下是校对软件如何发挥作用&#xff1a; 1.确保准确性&#xff1a;校对软件可以自动检查法律文书中的语法、拼写和标点等方面的错误。通过及时发现和修正这些错误&#xff0c;可以确保文…

自监督去噪:Recorrupted-to-Recorrupted原理分析与总结

文章目录 1. 方法原理1.1 相关研究1.2 研究思路1.3 小结 2. 实验结果3. 总结 文章地址: https://ieeexplore.ieee.org/document/9577798/footnotes#footnotes 参考博客: https://github.com/PangTongyao/Recorrupted-to-Recorrupted-Unsupervised-Deep-Learning-for-Image-Den…

C++如何改变文字的颜色(不同字显示不同颜色)

许多同学们在制作c游戏的时候只有黑白两种颜色。就像si人了一样 非常影响视觉效果&#xff0c;显得十分不好看&#xff0c;因此&#xff0c;我决定发一个改变文字颜色的文章&#xff01; 下面介绍方法&#xff1a; 在了解程序之前&#xff0c;首先好了解光的三原色已经三原色…

数据结构刷题训练——链表篇(三)

目录 文章目录 前言 1. 题目一&#xff1a;环形链表Ⅱ 1.1 思路 1.2 分析 1.3 题解 1.4 方法二 2. 题目二&#xff1a;复制带随机指针的链表 2.1 思路 2.2 分析 2.3 题解 总结 前言 在这个专栏博客中&#xff0c;我们将提供丰富的题目资源和解题思路&#xff0c;帮助读者逐步提…

浅谈智能配电房在海岛中的应用

安科瑞 华楠 摘要&#xff1a;以海陵岛旅游区海岛智能配电房设计方案为研究对象,从功能设计、逻辑设计和拓扑设计三方面进行 分析,得出契合海陵岛实际和海岛特点的智能配电房方案设计。通过对设计方案研究,总结提炼了海岛智 能配电房组成要素,为进一步提炼统一规范的智能配电房…

【深度学习】【风格迁移】Zero-shot Image-to-Image Translation

论文&#xff1a;https://arxiv.org/abs/2302.03027 代码&#xff1a;https://github.com/pix2pixzero/pix2pix-zero/tree/main 文章目录 Abstract1. Introduction相关工作3. Method Abstract 大规模文本到图像生成模型展示了它们合成多样且高质量图像的显著能力。然而&#x…

【网络编程】实现一个简单多线程版本TCP服务器(附源码)

TCP多线程 &#x1f335;预备知识&#x1f384; Accept函数&#x1f332;字节序转换函数&#x1f333;listen函数 &#x1f334;代码&#x1f331;Log.hpp&#x1f33f;Makefile☘️TCPClient.cc&#x1f340;TCPServer.cc&#x1f38d; util.hpp &#x1f335;预备知识 &…

未来C#上位机软件发展趋势

C#上位机软件迎来新的发展机遇。随着工业自动化的快速发展&#xff0c;C#作为一种流行的编程语言在上位机软件领域发挥着重要作用。未来&#xff0c;C#上位机软件可能会朝着以下几个方向发展&#xff1a; 1.智能化&#xff1a;随着人工智能技术的不断演进&#xff0c;C#上位机…

数据结构--最小生成树

数据结构–最小生成树 连通图 \color{red}连通图 连通图的生成树是 包含图中全部顶点的一个极小连通子图 \color{red}包含图中全部顶点的一个极小连通子图 包含图中全部顶点的一个极小连通子图。 若图中顶点数为n&#xff0c;则它的生成树含有 n-1 条边。对生成树而言&#xff…

RFID技术助力半导体制造行业自动化生产

由于芯片短缺问题和近2年海运拥堵和成本上升等因素&#xff0c;致使全球资本对于芯片制造工厂的投入增大&#xff0c;而中兴、华为的例子已经凸显出国产半导体供应链的重要性&#xff0c;除去地缘政治上的意义&#xff0c;发展半导体其实是中国经济的转型的必走之路。 半导体生…

Vue2(生命周期,列表排序,计算属性和监听器)

目录 前言一&#xff0c;生命周期1.1&#xff0c;生命周期函数简介1.2&#xff0c;Vue的初始化流程1.3,Vue的更新流程1.4&#xff0c; Vue的销毁流程1.5&#xff0c; 回顾生命周期1.,6&#xff0c;代码演示1.6-1&#xff0c;beforeCreate1.6-2&#xff0c;created1.6-3&#xf…

雨水旋流过滤器、旋流雨水过滤器、水力旋流雨水过滤器、旋流分离器、旋流沉砂一体机、旋流沉砂井

产品组成 主要材料&#xff1a;PE304不锈钢 组成&#xff1a;过滤器筒体、桶盖、截止阀&#xff08;选配&#xff09;、不锈钢滤网 工作原理 雨水由过滤器进水口进入时&#xff0c;水流被引导沿过滤器内壁切线方向进入筒体。在水力、重力等作用下&#xff0c;形成雨水紧贴过…

【基础类】—前端算法类

一、排序 1. 排序方法列表 2. 常见排序方法 快速排序选择排序希尔排序 二、堆栈、队列、链表 堆栈、队列、链表 三、递归 递归 四、波兰式和逆波兰式 理论源码

Unity之ShaderGraph 节点介绍 Utility节点

Utility 逻辑All&#xff08;所有分量都不为零&#xff0c;返回 true&#xff09;Any&#xff08;任何分量不为零&#xff0c;返回 true&#xff09;And&#xff08;A 和 B 均为 true&#xff09;Branch&#xff08;动态分支&#xff09;Comparison&#xff08;两个输入值 A 和…

wm8960没有声音

最近在imx6ull上调试这个声卡&#xff0c;用官方的镜像是能发声的&#xff0c;换到自己做的镜像上&#xff0c;就没有声音。 记录一下过程&#xff1a; 内核和设备树。只要有下面的显示&#xff0c;就说明加载成功。 再看一下aplay的显示 到此&#xff0c;驱动都是正常的。但…

每天一道leetcode:剑指 Offer 32 - II. 从上到下打印二叉树 II(适合初学者)

今日份题目&#xff1a; 从上到下按层打印二叉树&#xff0c;同一层的节点按从左到右的顺序打印&#xff0c;每一层打印到一行。 示例 例如: 给定二叉树: [3,9,20,null,null,15,7], 3 / \ 9 20 / \ 15 7 返回其层次遍历结果&#xff1a; [ [3], […