匈牙利算法
二分图最大匹配
给定一张二分图,有 个点, 条边。求最大匹配。
可以使用匈牙利算法求解,复杂度 。
如果使用 dinic 算法,可以做到复杂度为
dinic 算法详见 网络流初步-最大流算法。
具体来说,建立超级源点和超级汇点,然后建容量为 1 的边,跑最大流即为最大匹配。
匈牙利算法的本质就是找增广路,基于贪心思想。我们来看一个例子。
首先考虑给节点 1 寻找匹配。发现可以匹配右边的节点 1,则成功匹配。
然后考虑给节点 2 寻找匹配。发现能匹配的唯一一个节点 1 已经被占用,尝试让左边的节点 1 换一个匹配,即等价于找一个增广路。
这样就找到了这张图的最大匹配(3)。我们接下来考虑写一个递归函数实现这种协商找增广路的算法。
匈牙利算法
我们定义一个递归函数 bool dfs(int u)
,代表为节点 u
寻找匹配。
数组 int match[v]
表示右部图中节点 v
已经匹配上的左部图节点。
数组 bool used[v]
表示右部图中节点 v
是否已经在本轮中访问过。
则可以写出如下代码:
1 |
|
若 dfs(u)
返回 1,则代表成功为当前节点找到了一个匹配。
重点在第 10 行中 if 语句的条件:
match[v]==0
,代表当前节点v
还没有人跟他匹配,这样直接让u
跟v
匹配。dfs(match[v])
,代表可以让v
的原配和其他人匹配,这样也可以让u
跟v
匹配。
还要注意 used
数组。我们不会需要让一个右部节点 v
协商两次(因为如果第一次协商失败了,第二次一定失败)。used
数组需要在主程序中每次清零。因为是在找一条增广路的过程中不需要重复访问,两次不同的增广路需要清零。
模板
1 |
|
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 immix's blog!
评论