最小割的建模技巧
技巧0. INF 的使用
(u, v, INF) .
这条边不能割, u 和 v 的状态必须一样.
技巧1. 核心模型
若 x, y 不同, 则减少 v .
连双向边 (x, y, v) .
技巧2. 统治点
x 与集合 A 中一个不同, 则减少 v .
a[1]
/
v /
x <------> A ---- a[2]
\
\
a[3]
技巧3. 最大 - 最小转化
假装把所有都给取了, 这样条件会取反.
技巧4. A 中的都一样.
建立与 S 一定相连的点 v1, 即 (S, v1, INF) .
建立与 T 一定相连的点 v2, 即 (v2, T, INF) .
套用技巧2 .
技巧5. 反转源汇
e.g. 若 x, y 相同, 则减小 v .
e.g. 若 x 与 A 中的一个相同, 则减小 v .
把原图按照某种方式划分成一个二分图, 然后对 Y 部的点反转源汇, 即: 与 S 连通的意义是 X 部选择, Y部不选择, 与 T 连通的意义是 X 部不选择, Y 部选择.
最大权闭合图
闭合图为原图的一个子图, 满足任意一个节点的后继仍在闭合图中.
给原图的每个点以一个点权, 权值总和最大的闭合图称为最大权闭合图.
我们考虑利用最小割求解最大权闭合图.
首先, 为了权值最大, 我们贪心地将所有点权为正的点给选上, 但是这样可能会矛盾, 因为一个点权为正的点的后继可能点权为负.
我们考虑利用最小割, 减去最小的使方案合法的花费.
建立源点 S , 与 S 相连的意义是这个点被选择, 则初始的时候, 对于点权为正的点 i , 连边 (S, i, a[i]) .
建立汇点 T , 与 T 相连的意义是这个点没有被选择, 则初始的时候, 对于点权为负的点 i , 连边 (i, T, -a[i]) .
如果点权为正的 i 被选择了, 则它所有点权为负的后继都要被断开, 就会导致不连通, 所以直接将原图的边权给替换成 INF .
构造方案的时候, 就选择所有与 S 相连的点.
二分图最小点权覆盖, 最大点权独立集, 方格取数
二分图最小点权覆盖:
每一条边 (u, v) 都是一个限制条件, 要求 u 和 v 不能同时取得.
我们考虑先取得所有的, 然后减去最小的点权.
建立原点 S , 连向二分图左边的所有点, 与 S 连通的意义是左边的点被选择了, 或者右边的点没有被选择.
建立汇点 T , 二分图右边的所有点连向它, 与 T 连通的意义是左边的点没有被选择, 或者右边的点被选择了.
利用最小割最大流定理, 我们跑最大流, 再根据最后一次 BFS 得出的情报构造方案.
定理 覆盖集与独立集互补.
证明 即证明覆盖集的补集中的点两两独立.
反设存在 u , v 在覆盖集的补集中, 且 u , v 不独立, 那么覆盖剂没有覆盖边 (u, v) , 假设不成立.
二分图最大点权独立集:
对于一对互补的覆盖集, 独立集, 覆盖集的点权之和 + 独立集的点权之和 = 所有点权之和 S .
注意到 S 一定, 如果要最大化独立集的点权之和, 即最小化覆盖集的点权之和, 转化为了上述问题.
方格取数问题: n * m 的网格图中, 每个格子有一个点权. 选一些不相邻的格子, 最大化点权之和.
对于棋盘, 有一个经典的套路, 就是黑白染色.
本题黑白染色之后变成了二分图, 求最大点权独立集即可.
[BZOJ 3275] Number
题意
有 N (<= 3000) 个正整数, 从中选择出一些数, 最大化权值之和.
若 a , b 同时满足下述条件, 则不能同时被选: ①存在 c , a ^ 2 + b ^ 2 = c ^ 2 ②gcd(a, b) = 1 .
分析
任意两个偶数 2a, 2b 可以同时被选, 因为 (2a, 2b) = 2(a, b) > 1 .
任意两个奇数 2a+1, 2b+1 可以同时被选, 因为 (2a + 1) ^ 2 + (2b + 1) ^ 2 = 2(mod 4) .
建立源点 S , 与 S 连通表示选择.
建立汇点 T , 与 T 连通表示不选择.
建立汇点 T , 将所有偶数连向 T , 与 T 连通的意义是偶数被选择, 奇数没有被选择.
那么对于不能同时选择的 (a, b) , 我们强制连边 (a, b, INF) , 表示 a 和 b 必须舍去一个.
总的点权之和 - | 最小割 | .
[BZOJ 2039] 人员雇佣
题意
有 n 个人, 雇佣第 i 个人的花费为 a[i] , 任意两个雇佣的人 i, j 之间会产生利润 2 * E[i][j] , 雇佣的人与没有雇佣的人之间会产生花费 E[i][j] .
最大化总利润.
n <= 1000 , 1 <= a[i] <= 100000 .
分析
先假装所有人都雇佣了, 得到利润 sum , 再减去最小割.
建立源点 S , 与 S 连通的意义是被雇佣.
建立汇点 T , 与 T 连通的意义是没有被雇佣.
若 i 与 S 连通, 则花费 a[i] , 所以连边 (i, T, a[i]) .
考虑每一条边的影响: "任意两个雇佣的人 i, j 之间会产生利润 2 * E[i][j]" , 我们均分一下, 设如果 1 个人与 T 连通, 那么割去 E[i][j] , 连边 (S, i, E[i][j]) , (S, j, E[i][j]) . 若 i 与 j 均没有被雇佣, 那么这样就可以了. 但是有可能 i 被雇佣而 j 没有被雇佣, 或者 j 被雇佣但是 i 没有被雇佣, 此时只是减去了 1 个 E[i][j] , 根据题意还要减去 2 个, 所以连双向边 (i, j, 2 * E[i][j]) .
跑最小割即可.