【ACM】LeetCode第280场周赛 - 数组的最大与和 - 匈牙利算法/KM算法
题目:
解题思路:
- 题目的本质是将数组nums中的n个数字分配到不同的篮子中,每个数字分配到每个篮子时都有一个权值(按位与运算结果值),需要将整体分配方案的权值和最大化。
- 可以明显地看出是两类物品的匹配问题,又涉及权重的最大化,故可将题目抽象为一个二分图最大权匹配问题。
- 先考虑最朴素的方法,将每个数字和每个篮子的匹配方案都枚举一遍,计算出每种方案的权值和后比较获得最大值即可。算法时间复杂度为
。(当然是不可行的) - 当然,二分图匹配问题毕竟很经典了,如果能想到二分图匹配问题,就应当能想到可能存在已有算法(但是当然没学习过相关算法的话也很难现场想出解决算法)。实际上确实存在已有算法——KM算法,能够解决二分图最大权匹配问题,即找到二分图匹配方案中的权值和最大方案。
- 那么先上代码,再慢慢解释KM算法的原理(实际上我也只是听说过该算法,这次也好好学习一下)
代码:
- 代码根据参考文章[3]进行改进
1 | class Solution { |
KM算法细节解释:
- 建议先浏览参考文章[1]后再阅读本段,参考文章[1]中以简单的例子介绍了KM算法的整体流程,本段仅以笔者浅薄的知识做一些补充,相当于参考文章[1]的进阶版。
- KM算法本质上在匈牙利算法的基础上增加期望度机制。
- 初始化左半图每个number的期望度为该number最大可获得权值,右半图每个slot的期望度为0。
- 每次匹配时,只考虑边权等于相连number和slot期望度和的边。
- 当一次匹配中无法成功时,执行期望度更新操作:将涉及的所有number期望度减一、所有slot期望度加一。
- 可行性:
- 相当于限制了参与搜索的边的集合,使得权值较大的边能被优先搜索,保证了算法可行的充分性。
- 每次降低期望度时,将本次搜索中左半图所有点期望度减1、右半图所有点期望度加1。每次降低期望度时,设涉及到的左半图点个数为
,则涉及到的右半图点个数为 (不搜第 个左半图点时恰好匹配,而加入该点后不匹配,因此相关左半图点刚好比相关右半图点多一个)。 - 对已被匹配的边而言,对应左半图点期望度减1,右半图点期望度加1,故这些边仍然在被搜索的边集合中。期望度更新操作后,每个左半图点相关的权值稍小的边被加入搜索集中。由于更新时以1为粒度,所以能保证搜索过程中不会漏掉边,保证了算法可行的必要性。
参考:
- 标题: 【ACM】LeetCode第280场周赛 - 数组的最大与和 - 匈牙利算法/KM算法
- 作者: Fre5h1nd
- 创建于 : 2022-02-14 22:28:16
- 更新于 : 2023-12-11 18:25:21
- 链接: https://freshwlnd.github.io/2022/02/14/algorithm/leetcode-weekly-contest-280-4/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论