匈牙利算法

本贴最后更新于 180 天前,其中的信息可能已经渤澥桑田

二分图最大匹配算法(Hungarian Algorithm)

这个算法的操作与原理及其数学证明都很繁与困难,理解如何应用以及应用场景即可


一、概论介绍

  • 最大匹配:在二分图中最多能找到多少条没有公共端点的边(配对)

示例
image

不难发现,这个二分图的最大匹配是如下(不唯一)

但是最大匹配数为 4

image

  • 下面我们严谨的表述一遍最大匹配

在 G 的一个子图 M 中,M 的边集中的任意两条边都不依附于同一个顶点,则称 M 是一个匹配

选择这样的边数最大的子集称为图的最大匹配问题,最大匹配的边数称为最大匹配数

如果一个匹配中,图中的每个顶点都和图中某条边相关联,则称此匹配为完全匹配,也称作完备匹配。

  • 下面介绍两个基本概念(交替路与增广路)

交替路: 从一个未匹配点出发,依次经过非匹配边、匹配边、非匹配边...形成的路径叫交替路

增广路:从一个未匹配点出发,走交替路,如果途径另一个未匹配点(出发的点不算),则这条交替路称为增广路(agumenting path)

二、算法原理

原理:增广路的性质,增广路中的匹配边总是比未匹配边多一条,所以如果我们放弃一条增广路中的匹配边,选取未匹配边作为匹配边,则匹配的数量就会增加

匈牙利算法就是在不断寻找增广路,如果找不到增广路,就说明达到了最大匹配

可以数学证明这种算法得到的解即为最大匹配数

这个算法的严谨数学证明是比较难的,这里就不加以赘述了,感兴趣可以结合上学期离散数学的图论知识证明,不需要使用任何定理

举例使用:

起始状态尚未匹配,全部都是非匹配边和非匹配点

image

任意选中 x1 与任意其中一个点 y1 匹配

image

选中第二个点 x2,x1 没有已霸占 x2 的任何一个对象,故 x2 与任意一个 y2 匹配即可

image

选中 x3,发现 x3 的第一对象 y1 已经被 x1 占了,于是找出 x3 出发的的交错路径 x3-y1-x1-y4,把交错路中已在匹配上的边 x1-y1 从匹配中去掉,反而匹配剩余的边 x3-y1,x1-y4,这就是增广路技巧

具体操作中将使用 DFS 深度优先搜索

接着选择 x4,发现没有增广路,于是只好选择 y3

image

接着选择 x5,发现有增广路:x5-y4-x1-y1-x3-y7,于是变成如下

image

最后选择 x6,x6 无对象可选,而且没有增广路,于是 x6 没法匹配

此结果即为最大匹配

Code-hxw

typedef struct tagMaxMatch{ int edge[COUNT][COUNT]; bool on_path[COUNT]; int path[COUNT]; int max_match; }GRAPH_MATCH; void outputRes(int *path){ for (int i = 0 ; i<COUNT; i++) { printf("%d****%d\n",i,*(path+i)); } } void clearOnPathSign(GRAPH_MATCH *match){ for (int j = 0 ; j < COUNT ; j++) { match->on_path[j] = false; } } //dfs算法 bool FindAugPath(GRAPH_MATCH *match , int xi){ for (int yj = 0 ; yj < COUNT; yj++) { if ( match->edge[xi][yj] == 1 && !match->on_path[yj]) { match->on_path[yj] = true; if (match->path[yj] == -1 || FindAugPath(match,match->path[yj])) { match->path[yj] = xi; return true; } } } return false; } void Hungary_match(GRAPH_MATCH *match){ for (int xi = 0; xi<COUNT ; xi++) { FindAugPath(match, xi); clearOnPathSign(match); } outputRes(match->path); } int main() { GRAPH_MATCH *graph = (GRAPH_MATCH *)malloc(sizeof(GRAPH_MATCH)); for (int i = 0 ; i < COUNT ; i++) { for (int j = 0 ; j < COUNT ; j++) { graph->edge[i][j] = 0; } } graph->edge[0][1] = 1; graph->edge[0][0] = 1; graph->edge[1][1] = 1; graph->edge[1][2] = 1; graph->edge[2][1] = 1; graph->edge[2][0] = 1; graph->edge[3][2] = 1; //举例 for (int j = 0 ; j < COUNT ; j++) { graph->path[j] = -1; graph->on_path[j] = false; } Hungary_match(graph); }

参考学习资料:

**[1]**​匈牙利算法(二分图) - 神犇(shenben) - 博客园 (cnblogs.com)

  • 算法
    435 引用 • 254 回帖 • 24 关注
1 操作
XiaoweiH 在 2024-10-10 00:26:33 更新了该帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • Scala

    Scala 是一门多范式的编程语言,集成面向对象编程和函数式编程的各种特性。

    13 引用 • 11 回帖 • 160 关注
  • 前端

    前端技术一般分为前端设计和前端开发,前端设计可以理解为网站的视觉设计,前端开发则是网站的前台代码实现,包括 HTML、CSS 以及 JavaScript 等。

    245 引用 • 1338 回帖 • 2 关注
  • 周末

    星期六到星期天晚,实行五天工作制后,指每周的最后两天。再过几年可能就是三天了。

    14 引用 • 297 回帖 • 2 关注
  • 房星科技

    房星网,我们不和没有钱的程序员谈理想,我们要让程序员又有理想又有钱。我们有雄厚的房地产行业线下资源,遍布昆明全城的 100 家门店、四千地产经纪人是我们坚实的后盾。

    6 引用 • 141 回帖 • 590 关注
  • React

    React 是 Facebook 开源的一个用于构建 UI 的 JavaScript 库。

    192 引用 • 291 回帖 • 385 关注
  • JavaScript

    JavaScript 一种动态类型、弱类型、基于原型的直译式脚本语言,内置支持类型。它的解释器被称为 JavaScript 引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在 HTML 网页上使用,用来给 HTML 网页增加动态功能。

    729 引用 • 1278 回帖
  • Sphinx

    Sphinx 是一个基于 SQL 的全文检索引擎,可以结合 MySQL、PostgreSQL 做全文搜索,它可以提供比数据库本身更专业的搜索功能,使得应用程序更容易实现专业化的全文检索。

    1 引用 • 219 关注
  • 又拍云

    又拍云是国内领先的 CDN 服务提供商,国家工信部认证通过的“可信云”,乌云众测平台认证的“安全云”,为移动时代的创业者提供新一代的 CDN 加速服务。

    20 引用 • 37 回帖 • 573 关注
  • Google

    Google(Google Inc.,NASDAQ:GOOG)是一家美国上市公司(公有股份公司),于 1998 年 9 月 7 日以私有股份公司的形式创立,设计并管理一个互联网搜索引擎。Google 公司的总部称作“Googleplex”,它位于加利福尼亚山景城。Google 目前被公认为是全球规模最大的搜索引擎,它提供了简单易用的免费服务。不作恶(Don't be evil)是谷歌公司的一项非正式的公司口号。

    49 引用 • 192 回帖 • 1 关注
  • TGIF

    Thank God It's Friday! 感谢老天,总算到星期五啦!

    289 引用 • 4492 回帖 • 652 关注
  • 友情链接

    确认过眼神后的灵魂连接,站在链在!

    24 引用 • 373 回帖
  • Office

    Office 现已更名为 Microsoft 365. Microsoft 365 将高级 Office 应用(如 Word、Excel 和 PowerPoint)与 1 TB 的 OneDrive 云存储空间、高级安全性等结合在一起,可帮助你在任何设备上完成操作。

    5 引用 • 34 回帖
  • API

    应用程序编程接口(Application Programming Interface)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。

    79 引用 • 431 回帖
  • Maven

    Maven 是基于项目对象模型(POM)、通过一小段描述信息来管理项目的构建、报告和文档的软件项目管理工具。

    186 引用 • 318 回帖 • 255 关注
  • ZeroNet

    ZeroNet 是一个基于比特币加密技术和 BT 网络技术的去中心化的、开放开源的网络和交流系统。

    1 引用 • 21 回帖 • 643 关注
  • 机器学习

    机器学习(Machine Learning)是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。专门研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能,重新组织已有的知识结构使之不断改善自身的性能。

    83 引用 • 37 回帖
  • RYMCU

    RYMCU 致力于打造一个即严谨又活泼、专业又不失有趣,为数百万人服务的开源嵌入式知识学习交流平台。

    4 引用 • 6 回帖 • 54 关注
  • JRebel

    JRebel 是一款 Java 虚拟机插件,它使得 Java 程序员能在不进行重部署的情况下,即时看到代码的改变对一个应用程序带来的影响。

    26 引用 • 78 回帖 • 677 关注
  • 电影

    这是一个不能说的秘密。

    122 引用 • 608 回帖 • 1 关注
  • PostgreSQL

    PostgreSQL 是一款功能强大的企业级数据库系统,在 BSD 开源许可证下发布。

    22 引用 • 22 回帖 • 1 关注
  • Flutter

    Flutter 是谷歌的移动 UI 框架,可以快速在 iOS 和 Android 上构建高质量的原生用户界面。 Flutter 可以与现有的代码一起工作,它正在被越来越多的开发者和组织使用,并且 Flutter 是完全免费、开源的。

    39 引用 • 92 回帖 • 2 关注
  • 钉钉

    钉钉,专为中国企业打造的免费沟通协同多端平台, 阿里巴巴出品。

    15 引用 • 67 回帖 • 297 关注
  • 学习

    “梦想从学习开始,事业从实践起步” —— 习近平

    172 引用 • 516 回帖 • 1 关注
  • FlowUs

    FlowUs.息流 个人及团队的新一代生产力工具。

    让复杂的信息管理更轻松、自由、充满创意。

    1 引用
  • Jenkins

    Jenkins 是一套开源的持续集成工具。它提供了非常丰富的插件,让构建、部署、自动化集成项目变得简单易用。

    54 引用 • 37 回帖
  • CentOS

    CentOS(Community Enterprise Operating System)是 Linux 发行版之一,它是来自于 Red Hat Enterprise Linux 依照开放源代码规定释出的源代码所编译而成。由于出自同样的源代码,因此有些要求高度稳定的服务器以 CentOS 替代商业版的 Red Hat Enterprise Linux 使用。两者的不同在于 CentOS 并不包含封闭源代码软件。

    239 引用 • 224 回帖
  • OAuth

    OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是 oAuth 的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此 oAuth 是安全的。oAuth 是 Open Authorization 的简写。

    36 引用 • 103 回帖 • 30 关注