前置内容
知道:图- 知道:二分图,二分图匹配(匈牙利算法)
- 知道:二分图最大权完美匹配(KM算法)
- 知道:网络流算法(Dinic+当前弧优化)
- 知道:费用流算法(优化Dijkstra建图与SPFA建图)
- 知道:最小割在数值上等于最大流,但是最小割和网络流算法没有质的关系(引用)
所以就导致了求最小割的题目与求最大流的题目的建图方法不大同了。
入门建图模板
Total Flow S | 洛谷 P2936
- 告诉你每根水管的容量和两端连接的节点。
求 “A” 到 “Z” 的最大流。 - 最裸的网络流题目了,按题目要求建图即可。
【模板】最小费用最大流 | 洛谷 P3381
- 告诉你每根水管的容量、单位花费和两端连接的节点。
求源到汇的最大流,以及在最大流下的最小花费 - 最裸的费用流题目了,按题目要求建图即可。
二者取其一
二者取其一:
- 我们设两个集合 S S S 和 T T T
(1) 如果某个节点选进 S S S 集合会有一个收益,或者说如果某个节点不选进 S S S 集合会有一个花费,那么我们从 S S S(源点) 向这个节点连接一条容量为收益值/花费值的边。
(2) 如果某个节点选进 T T T 集合会有一个收益,或者说如果某个节点不选进 T T T 集合会有一个花费,那么我们从该节点向 T T T(汇点)连接一条容量为收益值/花费值的边。
(3) 如果两个节点必须同时选在一个集合里,则他们之间连一条容量为 I N F INF INF 的边 - 注意:
S S S 集合与 T T T 集合不一定表示选择的集合与不选择的集合
也可能表示某一种节点有两种选择,选择其一有一个收益,选择另一个也有一个收益。
现在总结一下,发现二者取其一题目无不两种类型:
- 舍弃流:最大收益 = 收益和 - 最小割
(1)一个点要么选有 a a a 收益,不选 b b b 收益,二者取一
(2)要么选 i i i 点, a a a 收益;要么选 j j j 点, b b b 收益;不能同时选。
(3)连的边表示收益,割掉这条边表示不要这个收益。我们求最大收益,就是求割掉边使得 S S S 和 T T T 不连通(此时每个节点要么和 S S S 连,要么和 T T T 连)的最小花费,所以需要用原来的收益和减去最小割。
(4)如果两个顶点不能同时选择在一个集合中(前提是这两个集合的连边要一个连 S S S 一个连 T T T,大概率是二分图),那么他们连一条容量为 I N F INF INF 的边,表示不能割断这条边,即不能割完后使得 i ∈ S ∧ j ∈ T i \in S \wedge j\in T i∈S∧j∈T
- 割流:最小花费 = 最小割 = 最大流
连的边表示割掉他们的花费
每个节点要么属于左部分,要么属于右部分。
或者说,要让 S S S 与 T T T 不连通。
如果某个节点必须属于集合 S S S,那就集合 S S S 向该节点连一条容量为 I N F INF INF 的边。
如果某个节点必须属于集合 T T T,那就该节点向集合 T T T 连一条容量为 I N F INF INF 的边。
一道难题 | 洛谷 P3931
- 给你一棵有根树,每条边都有一个割掉的花费。
问你,最少花费多少,才可以把树割开,使得所有叶子节点和根节点不连通。
边权是什么?不是收益,是割开他们的花费。
看来是割流的题目。
- 首先,根节点假设是一定在源点半边,故源点和根节点连容量为 I N F INF INF 的边。
- 既然如此,那么所有的根节点就一定在汇点半边,故所有结点向汇点连容量为 I N F INF INF的边
这个时候要注意一下连接的方向:有根树,故方向为根到叶子节点的方向,跑一个 D F S DFS DFS 即可得知方向,然后根据这个方向建边。
- 建图完成。跑完的最大流就是最小割就是最小花费。
善意的投票 | 洛谷 P2057
-
n n n 个人,每个人都有自己的睡觉意愿(想睡或不想睡),然后进行投票。
但是为了朋友可以投和自己意愿相反的票。
有 m m m 对朋友,如果每对朋友之间有相反投票则冲突加一。
若自己投票和自己意愿相反的结果则冲突加一。
问:冲突的最小值是多少。 -
首先该题是二者取一,每个人要么投想睡,要么投不想睡。
我们一开始,建图容易想到:意愿不想睡的,和 S S S 连容量 1 1 1 的边;意愿想睡的,和 T T T 连容量 1 1 1 的边。 -
那么我们想一想,这个冲突是什么?此时,冲突表示:割掉边的花费,而不是表示收益。
一开始不考虑朋友,明显是一个二分图, S S S 和 T T T 不连通,冲突为最大流=0 -
然后我们考虑朋友。如果这两个人的投票不同,那么冲突加一,也就是说:我们给他们两个人之间连一条容量为 1 1 1 的边,要么这两个人本来投票相同(这条边就不用割),要么这两个人的投票不同(最小割会把边给割掉,要么割掉某人的意愿边,要么割掉朋友的边)
-
然后我们把每一对朋友之间都这样连边,跑出来的最大流 = 最小割 = 冲突数了。
方格取数问题 | 洛谷 P2774
-
给定一个 n × m n\times m n×m的矩阵,每个位置的元素 M [ i ] [ j ] M[i][j] M[i][j] 表示取这个格子的收益。
你选取一些格子,但是这些格子不能有公共边。
求取出的数字的和最大为多少。 -
分析:拿格子相当于收益,从收益的角度分析,这题就是 舍弃流了。
那我们就要假设每个节点都拿,然后移除一些节点(割边),使得矛盾节点(相邻节点)消失( S S S 和 T T T 不连通)。 -
建图:
(1)考虑所有不能同时拿的节点,我们会向他们之间连一条容量为 I N F INF INF 的边。这样表示:他们要么全部属于 S S S 集合,要么全部属于 T T T 集合。
(2)这个时候,我们必须要求:如果 i i i 节点和 j j j 节点不能同时拿取,则必须收益边要 i i i 连 S S S 集合, j j j 连 T T T集合;或者 i i i 连 T T T 集合, j j j 连 S S S集合。不然无法满足要求。
(3)概括一下:相邻的点必须不能同时连接 S S S 集合 或同时连接 T T T 集合
(4)做法:按照点的坐标和的奇偶性,奇的话连接 S S S、偶的话连接 T T T。(当然反过来也可以)
因为是舍弃流,最大流等于最小割,等于花费。要求最终收益,就是总收益减去最小割。
小M的作物 | 洛谷 P1361
-
有 n n n 种作物,两块田。如果 i i i 作物种在 S S S 田会有 a i a_i ai 收益,种在 T T T 田会有 b i b_i bi 收益。
有 m m m 种配合。第 i i i 种配合包含一个作物集合 K i K_i Ki,如果该集合内的作物都种在 S S S 田则有额外收益 C i 1 C_{i1} Ci1 ,如果该集合内的作物都种在 T T T 田则有额外收益 C i 2 C_{i2} Ci2
问你最大收益为多少。 -
每种作物要么种在 S S S 田,要么在种在 T T T 田,两者取其一。
然后又是收益,所以是舍弃流。 -
建图:
一开始,想到的是,不考虑配合,就是普通的建图:
然后最大收益 = 收益和 - 最小割
-
但是对于配合怎么搞?可以这么想:
(1)如果该配合里的所有作物都在 S S S 田,则有收益 C i 1 C_{i1} Ci1,所以我们把 S S S 连向该配合(建一个虚点),边的容量为 C i 1 C_{i1} Ci1。
(2)该配合必须要求该集合里的作物都在 S S S 吧,那就把该配合的虚点向该集合的所有作物连一条 I N F INF INF 的边,表示他们之间无法被断开。
(3)相对应的,该配合里的所有作物全在 T T T 田,则有收益 C i 2 C_{i2} Ci2,我们再建一个虚点,该虚点向 T T T 连的边权就是 C i 2 C_{i2} Ci2 , 该集合内的所有点向该虚点连一条 I N F INF INF 的边。
(4)因为是舍弃流,最终答案 = 收益和 - 最小割。
拆点:入点和出点
- 上述建图方法主要是对边的一些操作。如果是对点的一些操作该怎么办呢?
我们可以拆点 - 看我的无敌总结!
奶牛的电信 | 洛谷 P1345
- 给你一个无向图,给你源点 S S S 和汇点 T T T
问你:最少删掉几个点(不能删 S S S 或 T T T 点),使得 S S S 和 T T T 之间不连通? - 首先,是删点不是删边,所以是拆点问题。
其次,该题和收益没啥关系,所以是网络流的拆点问题中的割流。 - 我们给每个可能可以删点的点,入点和出点之间连容量(花费)为 1 1 1 的边。
特殊地, S / T S/T S/T 点不能删,我们给他们入点和出点之间连容量(花费)为 I N F INF INF 的边。 - 因为只能割点,边不能删,所以边我们的容量(花费)为 I N F INF INF。
因为是割流,所以最小割 = 最大流。
黑手党 | 洛谷 P4662
-
这题和奶牛的电信很像,每个点割掉有一个给定的花费。
但是这题让你输出方案,也就是到底割掉了那些点。 -
求割点方案:我们只要在残存网络里面进行 D F S DFS DFS 的深搜,如果一个点的入点和出点都被搜到了,即该点没有被割掉。反之,该点被割掉了。
方格取数加强版 | 洛谷 P2045
-
给出一个 n × n n\times n n×n的矩阵,每一格有一个非负整数 A i j A_{ij} Aij
现在从 ( 1 , 1 ) (1,1) (1,1) 出发,可以往右或者往下走,最后到达 ( n , n ) (n,n) (n,n)。
每达到一格,把该格子的数取出来,该格子的数就变成 0 0 0。
这样一共走 K K K 次,现在要求 K K K 次所达到的方格的数的和最大是多少。 -
经过的点第一次会有收益,后续都无收益,想一想会发现是拆点的费用流的题目。
首先,入点和出点连一条容量为 1 1 1 ,花费(收益)为 − A i j -A_{ij} −Aij 的边。
然后,入点和出点连一条容量为 I N F INF INF,花费(收益)为 0 0 0 的边。
注意,两个不同点相连的方法:从 x x x 点连向 y y y 点的话,要 x x x 的出点连接 y y y 的入点,因为可以无限走,故容量为 I N F INF INF,花费(收益)为 0 0 0 -
最后注意源点连 ( 1 , 1 ) (1,1) (1,1) 的入点, ( n , n ) (n,n) (n,n) 的出点链接汇点
容量连多少?对,是 K K K,因为最多跑 K K K 次。花费(收益)当然是 0 0 0。
跑最小费用最大流即可。
答案就是最小费用的相反数。