网络流 & 二分图 & 线性规划
网络流
- P4177 [CEOI2008]order
题意 :有 个工作, 个机器, 每种机器可以租或者买, 给定 个工作的收益, 需要的机器和此次租这台机器的费用, 求最大化利益。
显然, 如果没有租的要求的话, 那么就是一个最大权闭合子图模板。
最大权闭合子图 :一个有向图,点有点权,选一个点必须要选它的所有后继, 求最大权值和。
具体建图 :新建一个源点 S 和汇点 T,将 S 与所有点权为正的点连边,流量为 , 并累加权值, 将 所有点权为负的点向 T 连边, 流量 。对于原图,建 ,流量 的边, 将累加的权值减去最大流 / 最小割既是最大权值和。
对于点权为正且无残余流量的点来说, 它没有被选,否则被选。
对于点权为负且无残余流量的点来说, 它被选, 否则没被选。 可以根据此输出方案。
好了, 这个题还有租的机器的方案,因为买对所有工作都有效, 租只对当前工作有效, 那么就把流量为 的改成租的代价再跑一遍最大流即可。
用最小割理解可能更简单一些。
2.P3749 [六省联考 2017] 寿司餐厅
题意 : 种寿司, 每种寿司有一个代号 和一个美味度 ,你可以不限次数吃一段区间的寿司, 收益为 , 每种收益 只能算一次。
假设最后你吃了 种代号为 的寿司, 你要支付的代价为 , 是给定的一个常数。
最大化收益 - 代价。
发现每种收益只能算一次这个现在比较奇怪, 而且要求的是收益 - 代价, 不难想到最大权闭合子图。
考虑怎么把这个图建出来 :你要得到 的收益, 那么一定得到了 和 的收益,因为你选择的是一段段的区间,那么就从 [i, j] 连向 [i,j - 1] 和 [i + 1, j],再对 的收益正负考虑它是从 S 连出来还是向 T 连过去。
把代价放在单点上考虑, 每吃一个代号为 的, 那么就要付出 的代价, 因为代号的 也只能算一次, 再把单点连向它的代号, 代号的代价即是 ,跑出最大流即可。
3.P1361 小M的作物
题意 : 种作物, A,B 两块地,每种作物只能种在一块地里面, 会有不同的收益。
另外有 种组合方式, 表示把该种组合的所有作物都种在一块地里面会有额外收益。
求最大收益。
二选一模型, 可以考虑最小割。
先考虑没有额外收益的情况 :源点表示选 A,汇点表示选 B,每个点与 S, T 分别连边, 流量为分别的权值, 最后用总和 - 最大流即可。
再考虑加入点集的答案, 这个点集无非只有三种情况 :
1.全种在 A 中,有 的贡献。 2. 全种在 B 中, 有 的贡献。 3. 只有部分在 A,无贡献。
我们考虑建出一个虚点来表示这个集合,分别与 S, T 相连边, 再与集合中所有的点连边, 边权为 , 表示这些边不能被删。
那么跑完最小割后, 如果边权为 的边没有割去,那么这些点一定都属于集合 A。 如果边权为 的边没有割去, 那么这些点一定都属于集合 B,那些边权为 的边一定不会被删。
感性理解即可,对于这种模型一定要多积累和多练。
4.P2764 最小路径覆盖问题
题意 :给你一张 DAG, 设 是 的一个简单路的集合, 如果 中每个点都恰好在 中一条路径上, 则称 是 的一个路径覆盖, 的最小路径覆盖即是所含简单路最少的 。
一个有向无环图的一条路径, 可以表示为除终点之外的所有点, 都向外伸出一条边。
把每个点拆成两个点 :入点和出点, 分别用 和 表示,放在一个二分图里面。
那么一条路径就是起点 没有匹配, 终点 没有匹配, 其他全部匹配的若干点。
可以发现 - 最大匹配数就是最小路径覆盖数, 输出方案就直接在右部点 DFS 即可。
5.P6061 [加油武汉]疫情调查
题意 :一个有向图, 边有边权, 每一个人要分配一些点集, 这个人就按照给定的顺序依次经过这些点并回到起点, 你要分配这些人, 使得他们的点集是一个 的划分。 特别地, 若一个人只分配到了一个点, 那么花费是 。
求最小代价。
可以发现一个人经过的路程是一个环, 还是若干个不相交的环, 这不就是最小环覆盖吗 ?
于是有一个很自然的想法 :先用 floyd 求出两两之间最短路, 再跑最小费用最大流, 因为可以走自环, 所以肯定是会满流的。
但这样做会超时,因为点数有 , floyd 就有 的复杂度, 考虑优化。
考虑减少边的数量, 具体的, 我们想用最小费用最大流的机制让它自己求出最短路。
具体建边如下 :
从 S 向每一个 连一条流量为 , 费用为 的边。
每一个 向 连一条流量为 ,费用为 的边,反向连流量 , 费用为 的边。
每一个 向 T 连流量为 , 费用为 的边。
对于原图上的边 , 建边 ,流量 ,费用为 。
优化后边数为 级别的, 可以通过。
6.P5038 [SCOI2012]奇怪的游戏
题意 :一个 的网格图, 初始每个格子上有一个值。 每次选择两个相邻的格子权值加 , 求最少次数使得所有数变成同一个数。
看到网格图先进行黑白染色成二分图, 则每次操作只会在一黑一白中进行,所以最后黑白所增加的权值一定相等。
假设黑色点有 个, 总权值为 , 白色点有 个, 总权值为 ,设最后达到相同的数是 , 则满足等式 : ,得到 , 分类讨论 :
若 , 则 可以直接算出来,再检验 的合法性, 具体地 :
建立源点 S,汇点 T,把每一个黑点要加的值 作为流量与 S 相连,表示要加上这么多次才能使该点满足, 对于白点同理,再从黑点向四周连白点, 跑最大流。
当入边和出边都满流时合法。
若 ,此时点的总数一定是偶数, 相当于 至少有一个为偶数, 此时满足单调性 :若 成立, 则 也成立, 因为可以把每个格子都加上 , 二分即可。
需要注意的是二分的上界要开的很大, 具体证明要用 Hall 定理, 这个之后再讲。
7.P2053 [SCOI2007]修车
题意 : 个车主来修车, 个技术人员维修。 第 辆车由第 个人维修要 的时间。
安排 个技术人员的维修的车和维修的顺序, 使得平均等待时间最小 。
显然一个人等待的时间就是他的技术人员修之前车时间的总和。
设第 个技术人员分别修了 个车, 则总时间为 :
, 也就是越先修的时间代价越高,倒数第 个修的时间系数为 。
那么把每一个技术人员拆成 个点, 表示他在修倒数第 个人的车的状态。
那么源点 S 连向所有的车, 流量为 , 每一个拆出来的点都与这 个车连边, 费用为 , 其中 表示拆的是倒数第 个点, 再向汇点 T 连边, 流量为 。
跑最小费用最大流即可。
可以证明最终选取的拆的点一定是连续的, 否则会不优。
8.P2050 [NOI2012] 美食节
题意 : 与 修车一模一样, 但数据范围大了许多。
考虑我们没有必要一次性把所有的边和点建出来,于是在最开始的时候只用把每一个厨师的倒数第一次的点建出来。
在 SPFA 找增广路时, 肯定只有一个厨师是匹配的, 于是我们把这个厨师的下一个时间段建出即可。
动态开点来优化费用流,是一个不错的优化方法。
9.CF976F Minimal k-covering
题意 : 一张二分图, 对于所有 , 求出使所有点的度数 需要保留边的最小数量,输出方案。
按照题意, 要求的是上下界最小流,但对于每一个 算一遍答案复杂度不对。
我们发现是度数至少为 限制了我们, 考虑怎么去掉它 ?
把至少转化为至多,那么就表示一个点至多去掉 条边,那么对于 从大到小考虑, 每次会把所有 点的从 S 流向它的流量加一,再在残量网络上增广。
那么这样的复杂度就是 了, 具体不会证明
10.P3980 [NOI2008] 志愿者招募
题意 : 给定一个序列 , 初始均为 , 你可以执行 种操作, 每次把区间 的值增加 ,费用为 ,可以任意次执行。 最后要求所有的 ,求最小费用。
费用流, 考虑怎么建边 :
发现这个至少不好满足, 考虑求至多, 具体建边如下 :
从 S 连向 , 容量为 ( 不小于最大的 ) 。
对于每一个 连向 , 容量为 ,表示第 个下标至多不流 个流量。
从 连向 T, 容量为 X。
对于每一个限制 , 从 向 连边,容量为 INF, 费用为 。
跑一次最小费用最大流即可。
拓展 :
我们将这个问题形式化 :给定 的 个区间 , 每个区间选择一次的代价为 ,最多选择 次, 最后要求点 的覆盖次数在 间, 求最小 / 最大代价。
同样把 连成一条链, 先确定最大流量 X。
用 边的流量刻画 被覆盖的次数, 流量要求在 。
对于一个区间, 建边 , 容量为 , 费用为 。
- P6967 [NEERC2016]Delight for a Cat
题意 : 一只猫在连续的 个小时内进行睡觉或进食两种动作, 一小时只能选一个。在每小时的收益分别为 。
要求在连续 个小时内, 必须要有至少 的时间睡觉和 的时间进食, 求最大收益。
先强制每个小时都睡觉, 再把一些睡觉改成进食, 对于每个区间要改的个数在 之间。
把每连续 个小时 看成点, 把修改一个小时 对点 看做区间。
那么最后就要求每个点覆盖的次数在 之间, 把 X 当做 后就没有下界了。
- P3511 [POI2010]MOS-Bridges
题意 :一个图, 边有正走和逆走的权值, 求一个最大边权最小的欧拉回路并输出方案。
先二分答案, 就变成了一些边只能倒着走, 一些边只能正走, 还有一些边随便走的混合图欧拉回路。
一个图存在欧拉回路的充要条件是每个点入度 = 出度,先把无向边任意选一个方向变成有有向边,再从 连一条容量为 的边, 表示反悔。
若发现有点的度数为奇数则无解。
否则, 如果一个点入度 - 出度 > 0,说明入边太多, 从 S 连向 , 流量为
如果一个点 < 0,说明出边太多, 从 连向 T,流量为 。
最后如果所有边满流则有解,输出方案请左转模板【欧拉路径】。
13.P2304 [NOI2015] 小园丁与老司机
14.P4542 [ZJOI2011]营救皮卡丘
15.P2469 [SDOI2010]星际竞速
16.P4194 矩阵
17.CF1288F Red-Blue Graph
18.CF708D Incorrect Flow
模拟费用流 Begin
先证明几个定理:
费用流的凸性 :根据 EK 算法, 每次增广的花费会不断增长,以费用为纵轴, 增广次数为横轴, 则画出来的图像是一个凸函数。
最小费用任意流 :每次增广负数费用路径直到费用为正。
(增量)最小费用任意流:每次往图中加入一个点和若干边, 并求解新的最小费用任意流。
我们只用考虑 "负路径" 和 "负环" 所造成的贡献。
可以用堆来维护已经增广过的路径和没有增广路径的最大值,具体方式因题而异。
费用流常用算法的效率较为低下,只能处理较小的数据范围。在一些特殊的费用流模型中,可以利用题目的特殊性质,结合数据结构 等技巧,设计更高效的费用流算法,称之为“模拟费用流”。
- P4694 [PA2013] Raper
题意 :有两个序列 和 , 每个 可以和 的 匹配, 收益是 , 求匹配 对的最大收益。 。
很容易建出一个费用流模型, 但显然是过不了的。
考虑模拟费用流, 每次枚举 , 把所有的 和已经匹配的 放到一个堆里面, 每次尝试取出最大值与 匹配, 若费用 则累加, 并把 放进堆里。
正确性可根据费用流增广得知。
- P5470 [NOI2019] 序列
题意 :两个序列 和 , 你需要在两个序列里分别选择 个下标, 要求至少有 个下标在两个序列中都被指定, 最大化选择的 和 的和。 。
既然要模拟费用流, 就先把暴力费用流建出来。
从源点 S 向 中的下标连边, 流量为 , 费用为 。
每一个 向对应的 连边, 流量为 ,表示选择了一对下标相同的数。
建立额外两点 , 连边 ,流量为 , 表示最多允许 个 匹配不同的 $b。
所有 向 连边, 向所有 连边, 流量为 。
再限制初始流量为 , 跑一遍最小费用最大流即可。 可以获得 64 pts 的高分(在考场上已经很高了)
看看这个图怎么找增广路, 具体来说, 有一下五种形式的增广路(找 cmd 贺的):
第一种方式表示 和 匹配;第二种方式表示 和 匹配 (i != j),要保证 有剩余流量;
第三种表示一个没选 但选了 的下标和一个没选 但选了 交换匹配 : 匹配 , 匹配 , 增加一点剩余流量。
第四种表示一个没选 但选了 的下标和 一个未匹配的 ,让 和 匹配, 原先匹配的点匹配 。
第五种类似, 表示一个没选 但选了 的下标和一个未匹配的 , 让 和 匹配, 原先匹配的点匹配 。
注意 :因为第二种匹配方式会减少一点自由流量, 要先保证 1, 3, 4, 5 种增广方案都不如第 2 种时再选择第 2 种。
考虑用 5 个堆 ,分别表示 和 都没选的 。
没选的 , 没选的 , 没选但 选了的 , 选了但 没选的 。
每次选出最优的合法的方式增广, 注意第二种方式增广要使自由流量 -1,第三种方式增广使自由流量 +1, 选择后再更新第 4, 5 个堆的答案即可。
- CF436E Cardboard Box
题意 : 个关卡,每个关卡可以花 的代价得到一颗星, 或者花 的代价得到两颗星星,或者什么都不做。
求获得 颗星星最小代价。 。
似乎本题不能用费用流模型来刻画。
依然考虑模拟费用流 / 反悔贪心,每次增广 颗星星, 我们有这么几种方式 :
把一个选 颗星的选 颗星,代价为 。
把一个选 颗星的选 颗星, 代价为 。
把一个选 颗星的降为选 颗星, 再把另一个选 颗星的选 颗星,代价为 。
把一个选 颗星的降为选 颗星, 再把另一个选 颗星的选 颗星,代价为 。
于是用 5 个堆分别维护 没选的 ,选了 1 个的 , 选了 1 个的 ,选了 0 个的 , 选了两个的 的最大值。
每次增广时找最大值即可, 写起来很舒服。
22.UOJ #455. 【UER #8】雪灾与外卖
23. CF280D k-Maximum Subsequence Sum
模拟费用流 End
24.P5458 [BJOI2016]水晶
25.P5331 [SNOI2019]通信
26.P4382 [八省联考 2018] 劈配
27.CF793G Oleg and chess
28.P5039 [SHOI2010]最小生成树
29.P6054 [RC-02] 开门大吉
30.P3756 [CQOI2017]老C的方块
31.P3973 [TJOI2015]线性代数
32.P5295 [北京省选集训2019]图的难题
33.CF103E Buying Sets
34.CF786E ALT
35.CF981F Round Marriage
36.P4066 [SHOI2003]吃豆豆
37.P4003 无限之环
38.
二分图
一些定义 & 定理
定义
图的匹配 :选出一些边,使得每两条边之间没有公共端点。
图的独立集:选出一些点, 使得每两个点之间没有边相连。
图的点覆盖 :选出一些点, 使得每条边至少有一个端点被选。
图的边覆盖:选出一些边, 使得每个点都至少被一条边覆盖。
图的团:选出一些点, 使得每两个点之间都有边相连。
定理
二分图最大匹配 : 匈牙利算法
每次找到增广路,把在匹配 P 中的边和不在匹配的边的状态
反,对于每一个左部点 DFS 寻找 即可,时间复杂度 。
二分图最小点覆盖 :等于最大匹配
Proof : 建立二分图匹配后, 每一个最小割都对应了一个点覆盖,对于中间一条边权 的边, 其左右至少会割一个点, 由于最小割等于最大流, 故得证。
二分图最大独立集 :等于总点数减去最小点覆盖。
Proof :任何一组独立集取补后得到一组点覆盖, 独立集和点覆盖一一对应。
二分图最小边覆盖 :等于最大独立集。
图的最大团 :等于补图的最大独立集。
二分图完美匹配 :若两侧点集分别为 X,Y,匹配数达到 的匹配称为完美匹配。
Hall 定理:
假设 ,令 表示与 相邻的点集,二分图存在大小为 的完美匹配当且仅当 ,有 。
Proof :
充分性 :若不存在一个大小为 的匹配,则从左部选出一个非匹配点出发进行增广,设访问到的左部点集合为 ,右部点集合为 ,由于无法增广成功所以增广过程的递归终止点必然在 中,但由于 , 必然可以继续增广, 矛盾。
必要性 :若存在完美匹配, 设 为 的匹配点, 则 两两不同, 对于任意点集有 。
推论 : 二分图最大匹配为 。
例题
1.P2423 [HEOI2012]朋友圈
题意 : 有两个国家 A 和 B,国家的每个人有一个值 。
对于 A 国, 若 ,则 和 有连边。
对于 B 国, 若 或者 为奇数, 则 和 有连边。
此外, 还有 个关系表示 A 的 和 B 的 有边。
求最大团。
最大团不好直接做, 考虑建出补图, 求一个最大独立集即可。
把所有点按照奇偶分为两个集合。
对于 A 的补图, 的内部互相连边, 的内部互相连边, 之间没有连边,故要选 的话只能选 个。
对于 B 的补图, 若 为偶数且 , 奇偶不同才有连边, 发现这是一个二分图。
利用二分图最大独立集 = 总点数 - 最大匹配即可。
于是枚举 A 中选哪些点, 那么 A 中选的点连向的 B 的点都不能选, 跑一遍最大匹配即可。
2.P3488 [POI2009]LYZ-Ice Skates
题意 :给定常数 ,初始有 的鞋子各 双, 一个号码为 的人可以穿一双编号在 的鞋子。
有 次操作, 每次有 个号码为 人来,求是否所有人都能穿一双鞋。
容易建出一个网络流模型 :源点 S 向每个号码连边, 流量为拥有这个号码的人数, 每个号码 向 的鞋子连边, 每个鞋子向汇点 T 连边, 流量为 , 那么有解就相当于所有边满流,但点数 显然是不可能的。
考虑我们只用知道是否满流, 于是使用 Hall 定理, 贪心的选择的 一定是一段连续的区间,否则一定不优。
于是我们要检验是否对于每个区间 都有 ,相当于 , 是一个常量不用考虑,把每一个 减去 后就是一个最大子段和问题, 使用线段树维护即可。
3.[ARC076D] Exhausted?
题意 : 一张二分图,左部 个点, 右边 个点。 左部每个点能和编号在 或 的右部点匹配, 求最大匹配数。 。
利用 Hall 定理, 我们只要求出最大的 即可。
先对所有线段按左端点从小到大排序,枚举左端点时维护右端点的答案。
先考虑 和 不交的情况 :枚举 , 则所有右端点 的点肯定都要选才更优,于是使用线段树。
类似扫描线, 每次把右端点 的值加 , 假设枚举的左端点是 , 则对答案的贡献是 , 把左边的值设为线段树维护的值即可。
再考虑 有交, 此时 确定, 我们只要贪心地选取所有点即可。
- CF1009G Allowed Letters
题意 :给定一个长度为 字符串, 字符集在 'a' - 'f', 重排这个字符串。有 个限制 :
给定 和字符集 , 表示第 位上只能选字符集 里的字符。
求字典序最小的字符串。 。
先考虑暴力网络流 :从源点 S 向每个位置连边, 每个位置向所能选的字符连边, 每个字符和汇点 T 连边, 容量为这个字符在大串的出现次数,若所有边满流则有合法解。
再考虑字典序最小 :可以贪心,从左往右枚举每个位置的字符, 再用网络流验证即可。
发现我们只想知道这个网络流是否满流, 相当于存在完美匹配。
而且字符集 'a' - 'f' 只有 6, 很难不想到枚举右部点的子集, 验证是否所有 即可。
于是做法就很显然了 :先预处理出每个右部点状态与左边匹配的个数, 可以求一个后缀和 ,再贪心地选取最小的字符, 再判断选出后的所有右部点合法即可。
5.P1963 [NOI2009] 变换序列
题意:给定 个数的一个序列 。
构造一个字典序最小的 阶排列 ,满足 。
发现每个点匹配的只有两个点, 直接倒序模拟匈牙利算法,即可保证字典序最小。
6.P5292 [HNOI2019]校园旅行
题意:一张图,每个点有一个 0 / 1 的编号。
多次询问, 每次询问给出 , 询问 之间是否存在一条路径使得把路径上所有的编号写成 01 串后为一个回文串。
- [AGC013F] Two Faced Cards
线性规划
参考了 fjzzq 的博客,在这里膜拜他!!!