二分图最大权匹配

图论 / 图匹配

本地源文件:docs/graph__graph-matching__bigraph-weight-match.md

二分图最大权匹配

二分图的最大权匹配是指二分图中边权和最大的匹配.

Hungarian Algorithm(Kuhn–Munkres Algorithm)

匈牙利算法又称为 KM 算法,可以在 𝑂(𝑛3)O(n3) 时间内求出二分图的 最大权完美匹配

考虑到二分图中两个集合中的点并不总是相同,为了能应用 KM 算法解决二分图的最大权匹配,需要先作如下处理:将两个集合中点数比较少的补点,使得两边点数相同,再将不存在的边权重设为 00,这种情况下,问题就转换成求 最大权完美匹配问题 ,从而能应用 KM 算法求解.

可行顶标

给每个节点 𝑖i 分配一个权值 𝑙(𝑖)l(i),对于所有边 (𝑢,𝑣)(u,v) 满足 𝑤(𝑢,𝑣) ≤𝑙(𝑢) +𝑙(𝑣)w(u,v)≤l(u)+l(v)

相等子图

在一组可行顶标下原图的生成子图,包含所有点但只包含满足 𝑤(𝑢,𝑣) =𝑙(𝑢) +𝑙(𝑣)w(u,v)=l(u)+l(v) 的边 (𝑢,𝑣)(u,v)

定理 1 : 对于某组可行顶标,如果其相等子图存在完美匹配,那么,该匹配就是原二分图的最大权完美匹配.

证明 1.

考虑原二分图任意一组完美匹配 𝑀M,其边权和为

𝑣𝑎𝑙(𝑀) =∑(𝑢,𝑣)∈𝑀𝑤(𝑢,𝑣) ≤∑(𝑢,𝑣)∈𝑀𝑙(𝑢)+𝑙(𝑣) ≤∑𝑛𝑖=1𝑙(𝑖)val(M)=∑(u,v)∈Mw(u,v)≤∑(u,v)∈Ml(u)+l(v)≤∑i=1nl(i)

任意一组可行顶标的相等子图的完美匹配 𝑀′M′ 的边权和

𝑣𝑎𝑙(𝑀′) =∑(𝑢,𝑣)∈𝑀𝑙(𝑢)+𝑙(𝑣) =∑𝑛𝑖=1𝑙(𝑖)val(M′)=∑(u,v)∈Ml(u)+l(v)=∑i=1nl(i)

即任意一组完美匹配的边权和都不会大于 𝑣𝑎𝑙(𝑀′)val(M′),那个 𝑀′M′ 就是最大权匹配.

有了定理 1,我们的目标就是透过不断的调整可行顶标,使得相等子图是完美匹配.

因为两边点数相等,假设点数为 𝑛n,𝑙𝑥(𝑖)lx(i) 表示左边第 𝑖i 个点的顶标,𝑙𝑦(𝑖)ly(i) 表示右边第 𝑖i 个点的顶标,𝑤(𝑢,𝑣)w(u,v) 表示左边第 𝑢u 个点和右边第 𝑣v 个点之间的权重.

首先初始化一组可行顶标,例如

𝑙𝑥(𝑖) =max1≤𝑗≤𝑛{𝑤(𝑖,𝑗)}, 𝑙𝑦(𝑖) =0lx(i)=max1≤j≤n{w(i,j)},ly(i)=0

然后选一个未匹配点,如同最大匹配一样求增广路.找到增广路就增广,否则,会得到一个交错树.

令 𝑆S,𝑇T 表示二分图左边右边在交错树中的点,𝑆′S′,𝑇′T′ 表示不在交错树中的点.

bigraph-weight-match-1

在相等子图中:

  • 𝑆 −𝑇′S−T′ 的边不存在,否则交错树会增长.
  • 𝑆′ −𝑇S′−T 一定是非匹配边,否则他就属于 𝑆S

假设给 𝑆S 中的顶标 −𝑎−a,给 𝑇T 中的顶标 +𝑎+a,可以发现

  • 𝑆 −𝑇S−T 边依然存在相等子图中.
  • 𝑆′ −𝑇′S′−T′ 没变化.
  • 𝑆 −𝑇′S−T′ 中的 𝑙𝑥 +𝑙𝑦lx+ly 有所减少,可能加入相等子图.
  • 𝑆′ −𝑇S′−T 中的 𝑙𝑥 +𝑙𝑦lx+ly 会增加,所以不可能加入相等子图.

所以这个 𝑎a 值的选择,显然得是 𝑆 −𝑇′S−T′ 当中最小的边权,

𝑎 =min{𝑙𝑥(𝑢) +𝑙𝑦(𝑣) −𝑤(𝑢,𝑣)|𝑢 ∈𝑆,𝑣 ∈𝑇′}a=min{lx(u)+ly(v)−w(u,v)|u∈S,v∈T′}

当一条新的边 (𝑢,𝑣)(u,v) 加入相等子图后有两种情况

  • 𝑣v 是未匹配点,则找到增广路
  • 𝑣v 和 𝑆′S′ 中的点已经匹配

这样至多修改 𝑛n 次顶标后,就可以找到增广路.

每次修改顶标的时候,交错树中的边不会离开相等子图,那么我们直接维护这棵树.

我们对 𝑇T 中的每个点 𝑣v 维护

𝑠𝑙𝑎𝑐𝑘(𝑣) =min{𝑙𝑥(𝑢) +𝑙𝑦(𝑣) −𝑤(𝑢,𝑣)|𝑢 ∈𝑆}slack(v)=min{lx(u)+ly(v)−w(u,v)|u∈S}

所以可以在 𝑂(𝑛)O(n) 算出顶标修改值 𝑎a

𝑎 =min{𝑠𝑙𝑎𝑐𝑘(𝑣)|𝑣 ∈𝑇′}a=min{slack(v)|v∈T′}

交错树新增一个点进入 𝑆S 的时候需要 𝑂(𝑛)O(n) 更新 𝑠𝑙𝑎𝑐𝑘(𝑣)slack(v).修改顶标需要 𝑂(𝑛)O(n) 给每个 𝑠𝑙𝑎𝑐𝑘(𝑣)slack(v) 减去 𝑎a.只要交错树找到一个未匹配点,就找到增广路.

一开始枚举 𝑛n 个点找增广路,为了找增广路需要延伸 𝑛n 次交错树,每次延伸需要 𝑛n 次维护,共 𝑂(𝑛3)O(n3)

参考代码

---|---

## Dynamic Hungarian Algorithm

原论文 [The Dynamic Hungarian Algorithm for the Assignment Problem with Changing Costs](https://www.ri.cmu.edu/publications/the-dynamic-hungarian-algorithm-for-the-assignment-problem-with-changing-costs/)

伪代码更清晰的论文 [A Fast Dynamic Assignment Algorithm for Solving Resource Allocation Problems](https://www.researchgate.net/publication/352490780_A_Fast_Dynamic_Assignment_Algorithm_for_Solving_Resource_Allocation_Problems)

相关 OJ 问题 [DAP](https://www.spoj.com/problems/DAP/)

算法思路

  1. 修改单点 𝑢𝑖ui![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 和所有 𝑣𝑗vj![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 之间的权重,即权重矩阵中的一行
     * 修改顶标 𝑙𝑥(𝑢𝑖) =𝑚𝑎𝑥(𝑤𝑖𝑗 −𝑣𝑗),∀𝑗lx(ui)=max(wij−vj),∀j![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
     * 删除 𝑢𝑖ui![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 相关的匹配
  2. 修改所有 𝑢𝑖ui![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 和单点 𝑣𝑗vj![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 之间的权重,即权重矩阵中的一列
     * 修改顶标 𝑙𝑦(𝑣𝑗) =𝑚𝑎𝑥(𝑤𝑖𝑗 −𝑢𝑖),∀𝑖ly(vj)=max(wij−ui),∀i![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
     * 删除 𝑣𝑗vj![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 相关的匹配
  3. 修改单点 𝑢𝑖ui![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 和单点 𝑣𝑗vj![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 之间的权重,即权重矩阵中的单个元素
     * 做 1 或 2 两种操作之一即可
  4. 添加某一单点 𝑢𝑖ui![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7),或者某一单点 𝑣𝑗vj![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7),即在权重矩阵中添加或者删除一行或者一列
     * 对应地做 1 或 2 即可,注意此处加点操作仅为加点,不额外设定权重值,新加点与其他点的权重为 0.

算法证明

  * 设原图为 G,左右两边的顶标为 𝛼𝑖αi![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 和 𝛽𝑗βj![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7),可行顶标为 l,那 𝐺𝑙Gl![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 是 G 的一个子图,包含图 G 中满足 𝑤𝑖𝑗 =𝑎𝑙𝑝ℎ𝑎𝑖 +𝑏𝑒𝑡𝑎𝑗wij=alphai+betaj![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 的点和边.
  * 在上面匈牙利算法的部分,定理一证明了:对于某组可行顶标,如果其相等子图存在完美匹配,那么,该匹配就是原二分图的最大权完美匹配.
  * 假设原来的最优匹配是 𝑀∗M∗![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7), 当一个修改发生的时候,我们会根据规则更新可行顶标,更新后的顶标设为 𝛼𝑖∗αi∗![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7), 或者 𝛽𝑗∗βj∗![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7),会出现以下情况:
    1. 权重矩阵的一整行被修改了,设被修改的行为 𝑖∗i∗![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 行,即 𝑣𝑖∗vi∗![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 的所有边被修改了,所以 𝑣𝑖∗vi∗![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 原来的顶标可能不满足条件,因为我们需要 𝑤𝑖∗𝑗 ≤𝑎𝑙𝑝ℎ𝑎𝑖∗ +𝑏𝑒𝑡𝑎𝑗wi∗j≤alphai∗+betaj![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7),但对于其他的 𝑢𝑗uj![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 来说,除了 𝑖∗i∗![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 相关的边,他们的边权是不变的,因此他们的顶标都是合法的,所以算法中修改了 𝑣𝑖∗vi∗![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 相关的顶标使得这组顶标是一组可行顶标.
    2. 权重矩阵的一整列被修改了,同理可得算法修改顶标使得这组顶标是一组可行顶标.
    3. 修改权重矩阵某一元素,任意修改其中一个顶标即可满足顶标条件
  * 每一次权重矩阵被修改,都关系到一个特定节点,这个节点可能是左边的也可能是右边的,因此我们直接记为 𝑥x![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7), 这个节点和某个节点 𝑦y![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 在原来的最优匹配中匹配上了.每一次修改操作,最多让这一对节点 unpair,因此我们只要跑一轮匈牙利算法中的搜索我们就能得到一个新的 match,而根据定理一,新跑出来的 match 是最优的.

以下代码应该为论文 2 作者提交的代码(以下代码为最大化权重版本,原始论文中为最小化 cost)

动态匈牙利算法参考代码

---|---

转化为费用流模型

二分图最大匹配 类似,二分图的最大权匹配也可以转化为网络流问题来求解.

首先,在图中新增一个源点和一个汇点.

从源点向二分图的每个左部点连一条流量为 11,费用为 00 的边,从二分图的每个右部点向汇点连一条流量为 11,费用为 00 的边.

接下来对于二分图中每一条连接左部点 𝑢u 和右部点 𝑣v,边权为 𝑤w 的边,则连一条从 𝑢u 到 𝑣v,流量为 11,费用为 𝑤w 的边.

另外,考虑到最大权匹配下,匹配边的数量不一定与最大匹配的匹配边数量相等,因此对于每个左部点,还需向汇点连一条流量为 11,费用为 00 的边.

求这个网络的 最大费用最大流 即可得到答案.此时,该网络的最大流量一定为左部点的数量,而最大流量下的最大费用即对应一个最大权匹配方案.

习题

UOJ #80. 二分图最大权匹配

模板题

---|---

* * *

> __本页面最近更新: 2026/1/7 08:56:54,[更新历史](https://github.com/OI-wiki/OI-wiki/commits/master/docs/graph/graph-matching/bigraph-weight-match.md)
>  __发现错误?想一起完善?[在 GitHub 上编辑此页!](https://oi-wiki.org/edit-landing/?ref=/graph/graph-matching/bigraph-weight-match.md "edit.link.title")
>  __本页面贡献者:[StudyingFather](https://github.com/StudyingFather), [Enter-tainer](https://github.com/Enter-tainer), [H-J-Granger](https://github.com/H-J-Granger), [Tiphereth-A](https://github.com/Tiphereth-A), [countercurrent-time](https://github.com/countercurrent-time), [NachtgeistW](https://github.com/NachtgeistW), [guodong2005](https://github.com/guodong2005), [310552025atNYCU](https://github.com/310552025atNYCU), [AngelKitty](https://github.com/AngelKitty), [Backl1ght](https://github.com/Backl1ght), [CCXXXI](https://github.com/CCXXXI), [Chrogeek](https://github.com/Chrogeek), [cjsoft](https://github.com/cjsoft), [diauweb](https://github.com/diauweb), [Early0v0](https://github.com/Early0v0), [ezoixx130](https://github.com/ezoixx130), [GekkaSaori](https://github.com/GekkaSaori), [Henry-ZHR](https://github.com/Henry-ZHR), [Ir1d](https://github.com/Ir1d), [Konano](https://github.com/Konano), [LovelyBuggies](https://github.com/LovelyBuggies), [Makkiy](https://github.com/Makkiy), [mgt](mailto:i@margatroid.xyz), [minghu6](https://github.com/minghu6), [P-Y-Y](https://github.com/P-Y-Y), [PotassiumWings](https://github.com/PotassiumWings), [SamZhangQingChuan](https://github.com/SamZhangQingChuan), [sshwy](https://github.com/sshwy), [Suyun514](mailto:suyun514@qq.com), [weiyong1024](https://github.com/weiyong1024), [Xeonacid](https://github.com/Xeonacid), [accelsao](https://github.com/accelsao), [GavinZhengOI](https://github.com/GavinZhengOI), [Gesrua](https://github.com/Gesrua), [Great-designer](https://github.com/Great-designer), [kxccc](https://github.com/kxccc), [lychees](https://github.com/lychees), [Peanut-Tang](https://github.com/Peanut-Tang), [SukkaW](https://github.com/SukkaW), [TachikakaMin](https://github.com/TachikakaMin)
>  __本页面的全部内容在**[CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/deed.zh) 和 [SATA](https://github.com/zTrix/sata-license)** 协议之条款下提供,附加条款亦可能应用