匈牙利算法简介:从二分图匹配到任务分配
匈牙利算法(Hungarian Algorithm)是组合优化领域最经典的算法之一,用于解决两类核心问题:二分图最大匹配和任务分配问题。它由匈牙利数学家 Dénes Kőnig 和 Jenő Egerváry 的理论奠基,后由 Harold Kuhn 于 1955 年正式提出。
什么是二分图?
在深入算法之前,我们需要先理解几个基本概念。
二分图(Bipartite Graph)是一种特殊的图结构,它的顶点可以被划分为两个互不相交的集合 U 和 V,使得图中的每一条边都连接 U 中的一个顶点和 V 中的一个顶点。
简单来说:二分图中的边只会”跨界”连接,不会在同一个集合内部连接。
匹配(Matching)是指图中一组没有公共顶点的边。换句话说,每个顶点最多只被一条边选中。
最大匹配就是包含边数最多的匹配。
匈牙利算法(二分图匹配版)
这是最常见的”匈牙利算法”,用于求解二分图的最大匹配。
核心思想:增广路
匈牙利算法的核心定理是 Berge 增广路定理:
一个匹配是最大匹配,当且仅当图中不存在增广路。
增广路(Augmenting Path)的定义:
- 路径的起点和终点都是未匹配的顶点
- 路径上的边交替出现”未匹配边”和”已匹配边”
增广路有一个神奇的性质:如果我们将增广路上所有边的状态取反(匹配变未匹配,未匹配变匹配),匹配的边数会增加 1。
算法步骤
1 | 1. 初始化匹配为空 |
Python 实现
1 | def hungarian_bipartite(graph, n_left, n_right): |
匈牙利算法(任务分配版)
另一种”匈牙利算法”用于解决带权二分图的最小/最大权匹配问题,也称为 Kuhn-Munkres 算法 或 分配问题算法。
问题描述
有 n 个工人和 n 项任务,每个工人完成每项任务的成本不同。如何分配才能使总成本最小?
这就是经典的任务分配问题,可以用一个 n×n 的代价矩阵表示。
算法步骤
1 | 1. 每行减去该行的最小值 |
时间复杂度
任务分配版的匈牙利算法时间复杂度为 **O(n³)**,在多项式时间内解决了这个组合优化问题。
应用场景
| 场景 | 算法版本 | 说明 |
|---|---|---|
| 红娘匹配 | 二分图匹配 | 男女配对,使配对数最大 |
| 任务分配 | 任务分配版 | 工人-任务最优分配 |
| 航班-登机口分配 | 任务分配版 | 最小化总等待时间 |
| 目标跟踪 | 任务分配版 | 多目标与多检测的最优关联 |
| 课程安排 | 二分图匹配 | 教师-教室-时间匹配 |
复杂度分析
- 二分图匹配版:O(V×E),其中 V 是顶点数,E 是边数
- 任务分配版:O(n³),其中 n 是矩阵维度
总结
匈牙利算法虽然有两个不同的版本,但它们都源于同一个数学理论:二分图的完美匹配理论。理解增广路的概念是掌握这个算法的关键。
无论是简单的二分图匹配,还是复杂的任务分配问题,匈牙利算法都提供了一个优雅且高效的解决方案。
延伸阅读:
- 《算法导论》第 26 章:最大流
- Harold W. Kuhn, “The Hungarian Method for the Assignment Problem” (1955)
- 网络流算法(Dinic、Edmonds-Karp)