二分图匹配学习笔记
搬运自我的洛谷同名文章。
Part 0. 前言 & 引理
本文主要讲述二分图匹配的练习题与进阶定理/概念,对于基础的匈牙利算法的过程不予叙述。
先贴个板子:
bool DFS(int x,int now){ for(int i=0;i<v[x].size();i++){ int to=v[x][i]; if(vis[to]!=now){ vis[to]=now; if(!match[to]||DFS(match[to],now)){ match[to]=x; return 1; } } } return 0; }
Part 1. 基础的最大匹配
二分图的题主要难点在于其建模。
考虑通过 (i+j)&1
将棋盘染成黑白两色,发现每一块骨牌都恰好覆盖一黑一白。所以可以对于每个黑色格子,将其与能和它一起被覆盖的白色格子连边,形成一边黑色格子一边白色格子的二分图。然后跑二分图最大匹配即可。
将行看成左部点,列看成右部点,放一个车相当于将其所在行和列连边。求这个二分图的最大匹配即可。
Part 2. 最小点覆盖和柯尼希定理
下面介绍一下柯尼希定理(König's Theorem)的定理内容。
在图论中,最小点覆盖是指在一个图中选取尽可能少的顶点,使得图中的每条边至少有一个端点被选中。König's Theorem 指出在二分图中,最小点覆盖的大小等于该图的最大匹配数。
知道了定理内容就可以做题了。
将 A 机器的
P6062 [USACO05JAN] Muddy Fields G
第一眼和前面的“棋盘覆盖”很像,但是发现木板长度任意,而且每个格子可以被覆盖多次。考虑到每个格子可以被覆盖多次,那么所有木板都顶着草地放一定不劣。具体举个例子,假设现在有 ..****.
这样一块地,那么在
处理完所有木板后,继续观察,发现一块泥地至少要被一块横着的或者竖着的木板覆盖,那么不妨将横着的木板设置为二分图的左部点,竖着的木板设置为二分图的右部点,一个格子看作一条连边,要求一个格子被覆盖,即要求这条连边至少有一个端点要被选中,求选中最少的木板使得所有连边至少有一个端点被选中。至此转化为二分图最小点覆盖的问题。
Part 3. 最大独立集和最小路径覆盖的结论
下面介绍二分图的最大独立集。二分图的最大独立集即选出二分图中最大的子集使得子集中的点两两之间无边直接相连。
仍然直接写出结论内容:二分图最大独立集大小 = 总点数 - 二分图最小点覆盖大小 = 总点数 - 二分图最大匹配。
乍一看也和前面的“棋盘覆盖”很像,发现按照同样的方法将棋盘黑白染色,黑格也只能攻击白格,白格也只能攻击黑格。那么将可以互相攻击的黑格和白格连边形成二分图,要求选出的不能互相攻击,也就是选出最多的点使得其两两之间无边相连,转化为二分图最大独立集的问题。
发现此时要选出的点不仅不能有直接联系,还不能有间接联系。于是通过传递闭包将所有间接联系转化为直接联系,跑二分图最大独立集即可。(如果存在联系则二分图连边。)
这道题我做的时候没有理清思路,导致没写最重要的传递闭包的过程,结果还拿了 95pts。
本文作者:xuchuhan
本文链接:https://www.cnblogs.com/xch0730/p/18672725/bipartite-matching
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步