2023.01.14 网络流在最优化问题中的应用 学习笔记
讲课人:戴江齐。
WC2023 Day2 上午的课。
1.[Google Code Jam 2022 Round 2]Saving the Jelly
记 \(r_x\) 表示红点 \(x\),\(b_x\) 表示黑点 \(x\)。如果 \(r_u\) 和 \(b_v\) 的距离不超过 \(r_u\) 和 \(b_1\) 的距离,那么在 \(r_u\) 和 \(b_v\) 之间连一条边,这样形成了一张二分图。有解的必要条件是二分图存在完美匹配。神奇的是这也是充分条件:考虑任求一组完美匹配,对每个 \(r_u\) 记 \(f_u\) 表示距离 \(r_u\) 比 \(r_u\) 的匹配点严格更近的黑点(如果不存在设为 \(-1\))。考虑下述过程:任取一个 \(r_v\),如果 \(f_v=-1\) 或 \(r_v\) 被经过过则停止该过程,否则找到 \(f_v\) 的匹配点,重复上述过程。一种情况是在 \(O(n)\) 步内找到了 \(r_v\) 使得 \(f_v=-1\),那么删去 \(r_v\) 和 \(r_v\) 的匹配点,最多会删 \(O(n)\) 次;另一种情况是花费 \(O(l)\) 步找到了一个含 \(O(l)\) 个点的环,对于环上的 \(O(l)\) 个 \(r_u\) 都将其匹配点调成 \(f_u\),这样环上每个红点离其匹配点都更近了,每个红点最多会被调 \(O(n)\) 次,总共会被调不超过 \(O(n^2)\) 次。上述两种情况做完后都应及时更新 \(f\) 一定会发生变化的红点的 \(f\),单看这两种情况都是 \(O(n^2)\) 的。
如何更新 \(f\)?实际上我们可以对每个 \(r_u\) 把所有黑点按到 \(r_u\) 的距离从小到大排序,并用指针维护当前 \(f\) 的值,这是 \(O(n^2\log n)\) 的。实际上,对于每个 \(r_u\) 我们可以把所有黑点分成四部分,分别是在 \(r_u\) 的右上方、左上方、左下方和右下方,然后把距离的绝对值拆开。以右上方的黑点为例,只需要按黑点的横纵坐标之和从小到大排序就好了。也就是说先 \(O(n\log n)\) 对所有黑点按四种要求分别排序,这样对于每个红点可以 \(O(n)\) 求出四个方向的黑点内部的顺序,再归并一下总复杂度就是 \(O(n^2)\) 的了。
于是调整的复杂度就降到了 \(O(n^2)\),不过时间复杂度的瓶颈在于求最大匹配。
2.AT_agc031_e [AGC031E] Snuke the Phantom Thief
枚举最终选了 \(k\) 个点,把这 \(k\) 个点按横坐标从小到大排序后,要求横坐标 \(\ge a\) 的点最多选 \(b\) 个,即前 \(k-b\) 个点的坐标都 \(<a\);横坐标 \(\le a\) 的点最多选 \(b\) 个,即后 \(k-b\) 个点的坐标都 \(>a\)。这样对于按横坐标排好序后的第 \(i\) 个点它的横坐标范围被定在了 \([L_i,R_i]\) 之间,并且 \(L,R\) 都是不减的,所以只要存在一种合法方案那么一定可以通过调整法得到一种满足 \(k\) 个点的横坐标不减的合法方案。纵坐标同理。
设 \((f,v)\) 表示容量为 \(f\),费用为 \(v\) 的边。源点向左边的 \(k\) 个点(代表横坐标限制)连 \((1,0)\) 的边,右边的 \(k\) 个点(代表纵坐标限制)向汇点连 \((1,0)\) 的边,中间把每个珠宝拆点拆成 \(n\) 个入点和出点,左右 \(2k\) 个点分别和所有满足限制的珠宝的入点和出点连 \((1,0)\) 的边,跑最大费用最大流即可。
直接建图有 \(O(n)\) 个点,\(O(n^2)\) 条边,连边时可以用 学习笔记-2021.12.23 「2021-12-23 省选模拟赛」背包 (bag) 的技巧把边数降到 \(O(n)\) 条。
3.P4003 无限之环
考虑怎么判断一张给定图是否会漏水,我们把方格黑白染色,每个方格在方格内部四条边界线处建一个点,对于黑格从源点向与水管接通的边界对应的点连流量为 \(1\) 的边,对于白格从与水管接通的边界对应的点向汇点连流量为 \(1\) 的边,对于两个格子如果存在公共边就从该边在黑格中对应的点向该边在白格中对应的点连流量为 \(1\) 的边,跑最大流看是否满流即可。
设 \((f,v)\) 表示容量为 \(f\),费用为 \(v\) 的边。我们在原图基础上把所有流量为 \(1\) 的边改成 \((1,0)\) 的边。实际上,能旋转的水管只有两个接口且接口所在边为邻边和三个接口的水管。对于前者,假设源点连向了左边和上面,那从左边向右边连 \((1,1)\) 的边,从上面向下面也连 \((1,1)\) 的边;对于后者,假设源点连了左边、上面和右边,那从左边向下面连 \((1,1)\) 的边,从右边向下面连 \((1,1)\) 的边,从上面向下面连 \((1,2)\) 的边。可以发现,这样的连边足以保证所有旋转方式都可能出现。
4.P4043 [AHOI2014/JSOI2014]支线剧情
原图最终会被若干条从 \(1\) 出发到某个点终止的路径覆盖使得每条边至少被覆盖一次。对原图中一条 \(u\) 向 \(v\) 边权为 \(w\) 的边,在新图上从 \(u\) 向 \(v\) 连上下界为 \([1,\inf]\) 费用为 \(w\) 的边,从每个点向 \(1\) 连一条上下界为 \([0,\inf]\) 费用为 \(0\) 的边,跑无源汇上下界最小费用可行流即可。
无源汇上下界最小费用可行流的求法是,先让每条边流量达到下界,根据每个点的流量平衡决定和超级源点 \(S\) 还是超级汇点 \(T\) 连边,然后从 \(S\) 向 \(T\) 直接跑最小费用最大流就好了。原因是 \(S\) 到 \(T\) 的任意一组最大流都和某组原图的可行流一一对应,且该最大流相比对应可行流多经过的边都是费用为 \(0\) 的边,而我们保证了这组最大流费用最小,所以也保证了所求的可行流费用最小。(感谢 Linshey)
5.P3227 [HNOI2013]切糕
见 2023.01.07 图论&2023.01.08 网络流 学习笔记 P18。
6.CF1630F Making It Bipartite
如果 \(x,y\) 都在序列中出现过且 \(x|y\),则从 \(y\) 向 \(x\) 连一条有向边,这样得到一张图 \(G\)。\(G\) 是二分图当且仅当原序列中不存在三个数 \(x,y,z\) 使得 \(x|y,y|z\)。问题转化为从 \(G\) 中选出尽量多的点使得它们在 \(G\) 中的导出子图的最长路经过点数不超过 \(2\),即每个点只有入度或出度。
把 \(G\) 复制一遍得到 \(G'\),设 \(G\) 中的 \(x\) 点对应到 \(G'\) 中是 \(x'\) 点,令 \(H=G+G'\),再在 \(H\) 中加上 \(x'\rightarrow x\) 的边,显然 \(H\) 是 DAG。下面证明 \(G\) 中选出的最多点数等于 \(H\) 的最长反链大小。
对于一种 \(G\) 选出最多点数的方案中的每个点 \(x\),如果其只有入度则在 \(H\) 中选 \(x'\),只有出度在 \(H\) 中选 \(x\)(既没有入度也没有出度任选一组归类)。显然在 \(G\) 中选出的点两两没有边,在 \(G'\) 中选出的点也两两没有边。如果存在 \(x'\) 和 \(y\) 使得 \(x'\) 可以走到某个 \(z'\),\(z'\) 走到 \(z\),\(z\) 再走到 \(y\),那么在 \(G\) 中一定有 \(x\) 到 \(y\) 的边,但根据我们在 \(H\) 中的选点方案可知 \(x\) 在导出子图中只有入度,\(y\) 在导出子图中只有出度,矛盾!所以 \(G'\) 和 \(G\) 中选出的点间也没边,故这是一组反链。
对于一种 \(H\) 的最长反链,首先 \(x\) 和 \(x'\) 不会被同时选,如果 \(x\) 或 \(x'\) 被选了那就在 \(G\) 里面选 \(x\)。对于 \(G\) 中的某个点 \(x\),如果 \(x\) 和 \(x'\) 在 \(H\) 中被选中的是 \(x'\),那么 \(G\) 中被选定的点中一定不存在 \(y\) 使得 \(y|x\),否则 \(y,y'\) 都可以被 \(x'\) 走到,与最长反链矛盾!也就是说 \(G\) 被选定的点中不存在 \(x\) 的因数,故 \(x\) 只有入度。同理可证明对于 \(G\) 中的某个点 \(x\),如果 \(x\) 和 \(x'\) 在 \(H\) 中被选中的是 \(x\),那么 \(x\) 在 \(G\) 中只有出度。所以这种 \(G\) 中选点方案合法。
所以两者相等。关于建图,一种比较厉害的方法是点数 \(\le B\) 时 \(O(B^2)\) 暴力建,点数 \(>B\) 时 \(O(V\ln V)\) 建,其中 \(V\) 是值域。
7.AT_agc029_f [AGC029F] Construction of a tree
建立二分图,左侧是 \(n\) 个点,右侧是 \(n-1\) 个集合,每个集合向其包含的点连边。如果能连出树,那对于右边的任意 \(k\) 个集合都有与左侧相连的点数至少为 \(k+1\),否则会连出环就连不出树了。事实上,这个条件也足够充分,我们先求出原图的一组完备匹配,左侧有恰好一个点 \(r\) 没有被匹配。重复以下过程:找到所有右侧与 \(r\) 相连的点,把它们都加入候选集合(如果已加入过就不用再加了),从候选集合中取出一个点 \(u\),并找到左侧与 \(u\) 匹配的点 \(v\),从二分图中删去 \(r\) 和 \(u\),并在原图中加一条 \((r,v)\) 的边,现在除了 \(v\) 外其它点都有匹配,重复上述过程直至在第二步中候选集合为空为止。如果所有点都被访问过了,由于每次新加入的一条边的两端点在加入这条边前有一个点根本没连过边,所以加入 \(n-1\) 条边后连成了一棵树;而如果左侧找了 \(a(1\le a<n)\) 个点后找不动了,说明右侧与左侧这 \(a\) 个点相连的点有恰好 \(a-1\) 个点,那么对右侧剩下的 \(n-1-(a-1)=n-a\) 个点,左侧与其相连的点至多只有 \(n-a\) 个,矛盾了!所以上述情况一定不可能出现,即有解一定能被如此构造出。
8.QOJ#1197. Draw in Straight Lines
「一个格子最多被染色两次」说明对每个格子只有不染、染白、染黑、先染白再染黑、先染黑再染白五种情况,而格子一开始都是白的,且「一个格子不能在被染白后再被染黑」,所以只剩不染、染黑、先染黑再染白三种情况了,即应做完所有染黑操作后再做所有染白操作。
考虑问题有哪些限制。1.「将连续的长度为 \(l\) 的横向或纵向的方格染为某种颜色(黑或白),代价为 \(al + b\)」可看成这组方格中最靠左上的一个代价是 \(a+b\),其余的代价是 \(a\);2. 如果有两次横着连续覆盖的操作相交了,可以发现一定可把这两次操作调整成不交得到一种更优方案,所以每个格子最多被横着覆盖一次(竖着同理);3. 对于一个黑格,不能在上面进行染白的操作,如果没被横向或纵向染黑过,那必须得花费 \(c\) 的代价单独染黑;4. 对于一个白格,其不能同时被横向和纵向染黑(因为「一个格子最多被染色两次」),如果被染黑过一次,不妨设为横向染黑,根据前面的分析该格一定不会再被横向染白,所以只可能被纵向染白或单独染白。
考虑建图求最小割。对每个格子 \((i,j)\) 建立四个点 \(b_r(i,j),w_r(i,j),b_c(i,j),w_c(i,j)\),取值 \(0,1\) 分别表示该格是否被横向染黑、横向染白、纵向染黑、纵向染白过,根据上述限制一一建边:1. \(S\) 向 \(b_r(i,j),w_c(i,j)\)、\(w_r(i,j),b_c(i,j)\) 向 \(T\) 连流量为 \(a\) 的边,\(b_r(i,j),w_c(i,j)\) 向 \(T\)、\(S\) 向 \(w_r(i,j),b_c(i,j)\) 连流量为 \(0\) 的边,前者被割掉代表对应变量取值为 \(1\),后者被割掉代表对应变量取值为 \(0\),由于两条边只能割恰好一条,所以它们的流量都应加上 \(\inf\)。同时对于所有 \(b_r(i,j)=1\)(\(w_r,b_c,w_c\) 同理),若 \(j=1\) 则给 \(S\) 到 \(b_r(i,j)\) 的边流量加 \(b\),若 \(j>1\) 则从 \(b_r(i,j-1)\) 向 \(b_r(i,j)\) 连流量为 \(b\) 的边。2. 从 \(w_r(i,j)\) 向 \(b_r(i,j)\) 连流量为 \(\inf\) 的边(实际上 \(w_r(i,j)\) 和 \(b_r(i,j)\) 同时为 \(1\) 是不优的,所以此边不连仍能得到正确答案)(\(w_c,b_c\) 同理)。3. 对于黑格 \((i,j)\),从 \(w_r(i,j)\) 向 \(T\)、\(S\) 向 \(w_c(i,j)\) 连流量为 \(\inf\) 的边,并从 \(b_r(i,j)\) 向 \(b_c(i,j)\) 连流量为 \(c\) 的边。4. 对于白格 \((i,j)\),从 \(b_c(i,j)\) 向 \(b_r(i,j)\) 连流量为 \(\inf\) 的边,并从 \(w_c(i,j)\) 向 \(b_r(i,j)\) 连流量为 \(c\) 的边(\(b_c,w_r\) 同理)。
9.P5470 [NOI2019] 序列
设 \((f,v)\) 表示容量为 \(f\),费用为 \(v\) 的边。考虑一张左右各有 \(n\) 个点的二分图,源点向左边第 \(i\) 个点连 \((1,a_i)\) 的边,左边第 \(i\) 个点向右边第 \(i\) 个点连 \((1,0)\) 的边,右边第 \(i\) 个点向汇点连 \((1,b_i)\) 的边。加入两个虚点 \(C,D\),左边每个点向 \(C\) 连 \((1,0)\) 的边,\(C\) 向 \(D\) 连 \((K-L,0)\) 的边,\(D\) 向右边每个点连 \((1,0)\) 的边。答案就是这张图流量为 \(K\) 的最大费用流。
考虑模拟费用流,每次增广一条费用最大的路径。如果 \(C\rightarrow D\) 的边未满流,则从 \(a,b\) 未选的集合中各选一个最大的;否则,有两种情况,一种是在 \(a,b\) 都未选的集合中选出两个下标相同且和最大的数,另一种是给已选的某个 \(a_i\)(但没选 \(b_i\))加入对应的 \(b_i\),这样原来和 \(a_i\) 匹配且下标不相等的数就空出来了,此时可以在 \(a\) 未选的集合中选一个最大的数与 \(a_i\) 原来匹配的数匹配,即在 \(a\) 已选过但 \(b\) 没选过的集合中选一个最大的 \(b\) 并在 \(a\) 没选过的集合中选一个最大的 \(a\)(第二种情况 \(a,b\) 互换同理),两种情况取更优的那种。如果选出的数在已选的集合中有下标一样的,则可以给 \(C\rightarrow D\) 的边退流。维护若干个堆即可。
时间复杂度 \(O(n\log n)\),空间复杂度 \(O(n)\)。
10.Gym104090H RPG Pro League
首先要求出最多能组成多少支队伍,二分组成队伍支数 \(t\)。建一张二分图,左边是每个人,右边是每个职业(\(D,S,B,D/S\)),源点向第 \(i\) 个人连流量为 \(1\) 的边,每个人向其可以担任的职业连流量为 \(\inf\) 的边,每个职业向汇点连流量为 \(t\) 的边,跑最大流判断是否满流。实际上左边的点根据它们的连边可以合并成 \(2^3-1=7\) 个点,同时根据 Hall 定理的推论(本文加强 \(2\) 部分)可知只要对于右边的 \(2^4-1\) 个非空子集 \(S\),计算出左边与它相连的总点数 \(N(S)\)(左边的点是带权的,一个点的点权是它代表的人数),答案就是 \(\lfloor\frac{N(S)}{|S|}\rfloor\) 的最小值。这个方法在知道每个 \(N(S)\) 后能在 \(O(2^4)\) 时间内求出最多能组成的队伍支数。
求出队伍支数 \(t\) 后,考虑一个贪心:按照费用从大到小考虑删去每个人后是否还能组成 \(t\) 支队伍,如果不能说明这个人一定要选,否则一定不会选这个人。这个贪心的正确之处在于我们跑最小费用最大流时实际上每次增广的是一条费用最小的路径,按路径费用从小到大考虑每条路径,如果该路径能加入,则流量会 \(+1\),否则流量不会变,所以在按路径费用从大到小考虑每条路径是否能不选时,删去后最大流不变当且仅当该路径在按路径费用从小到大考虑时未被加入。
至此,我们可以通过对左边 \(7\) 个点每个点都维护一个 set,每次判断当前费用最大的人是否可被删除,这样初始时我们可以根据上述贪心选出总费用最小的 \(4t\) 个人。每次更新一个人的费用,如果该人原本就在最优解中,那新的最优解可能是原来的最优解,也可能是在原来的最优解基础上这个人被某个集合中未被选的人中费用最小的一个人代替了;同理,如果该人原本不在最优解中,那新的最优解可能是原来的最优解,也可能是在原来的最优解基础上这个人把某个集合中被选的人中费用最大的一个人代替了。这都可以在 \(O(7\times(\log n+2^4))\) 时间内完成判定。
总时间复杂度 \(O(q\log n)\),空间复杂度 \(O(n)\)。
11.URAL1833 Hopes of Rowing
如果要求每个 \(x_i\) 都是整数,考虑对每个限制 \(x_{u_i}+x_{v_i}\ge 1\),在 \(u_i\) 和 \(v_i\) 间连一条边,点 \(i\) 选和没选表示 \(x_i=1\) 和 \(x_i=0\),限制相当于每条边两端点至少要选一个,也就是最小点覆盖。如果建出来的图是二分图,由于可以对该二分图建出网络流的图,且每条边流量上限都是整数,根据「网络流整数性」可知存在最优解使得每个点要么被选要么不被选。令 \(y_i,z_i\in[0,1]\),\(x_i=\frac{y_i+z_i}{2}\),每个限制是 \(y_{u_i}+z_{v_i}\ge 1\),\(z_{u_i}+y_{v_i}\ge 1\),如果能求出 \(y,z\) 则也能求出 \(x\),同时如果已知 \(x\) 可以让 \(y_i=z_i=\frac{x_i}{2}\) 也满足条件。对 \(y,z\) 共 \(2n\) 个变量建出的图是二分图,可以跑最大流直接求最小点覆盖。
12.UOJ#455. 【UER #8】雪灾与外卖
设 \((f,v)\) 表示容量为 \(f\),费用为 \(v\) 的边。先建出费用流的图:把每个坐标看成一个点,相邻坐标间连一条 \((\inf,1)\) 的双向边,源点向有老鼠的坐标连 \((1,0)\) 的边,第 \(i\) 个洞的坐标向汇点连 \((c_i,w_i)\) 的边。考虑按坐标从左往右 dp,设 \(dp_{i,x}\) 表示考虑坐标不超过 \(i\) 的点,当前有向流量(从源点流出的为正)为 \(x\) 的最小花费,加入老鼠就是向右平移一格,加入第 \(i\) 个洞就是和以 \((-c_i,c_iw_i),(0,0)\) 为两端点的线段做闵可夫斯基和,加入 \(k\) 个连续的既没有老鼠也不是洞的坐标就是所有 dp 值加上第二维下标的绝对值乘 \(k\),这都可以通过用平衡树维护斜率相同的 dp 连续段来实现。
时间复杂度 \(O((n+m)\log(n+m))\),空间复杂度 \(O(n+m)\)。
13.CF1229F Mateusz and Escape Room
设 \(([l,r],v)\) 表示容量下界为 \(l\),上界为 \(r\),费用为 \(v\) 的边。先建出费用流的图:把每个位置看成一个点,相邻位置间连一条 \(([0,\inf],1)\) 的双向边,源点向位置 \(i\) 连 \(([a_i,a_i],0)\) 的边,位置 \(i\) 向汇点连 \(([l_i,r_i],w_i)\) 的边,跑有源汇上下界最小费用可行流。记 \(nx(i)=i\bmod n+1,la(i)=(i+n-2)\bmod n+1\),设 \(x_i\) 表示连接 \(i,nx(i)\) 的边的流量,其中 \(i\rightarrow nx(i)\) 为正方向,也就是要求 \(l_i\le a_i-x_i+x_{la(i)} \le r_i\)。
假设 \(x_n\) 已经固定,那么就相当于断环成链。考虑按位置从小往大 dp,设 \(dp_{i,x}\) 表示考虑不超过 \(i\) 的位置,当前有向流量(从源点流出的为正)为 \(x\) 的最小花费,加入 \(a_i\) 个球就是向右平移 \(a_i\) 格,加入第 \(i\) 个位置就是和以 \((-r_i,0),(-l_i,0)\) 为两端点的线段做闵可夫斯基和,加入 \(i\rightarrow nx(i)\) 的边就是所有 dp 值加上第二维下标的绝对值,这都可以通过用两个堆维护 dp 值斜率的转折点来实现(两个堆的分界点是全局最小值处,可以用堆维护的原因是 dp 值的斜率的绝对值不超过 \(n\))。
根据「网络流整数性」可知存在最优解使得每条边流量都为整数,所以让每条边流量可以为小数也不影响答案。假设求出了一组解 \((x_1,\cdots,x_n)=(a_1,\cdots,a_n)\) 和另一组解 \((x_1,\cdots,x_n)=(b_1,\cdots,b_n)\),那么 \((x_1,\cdots,x_n)=(\frac{a_1+b_1}{2},\cdots,\frac{a_n+b_n}{2})\) 也是一组合法解。即设 \(x_n=a\) 时的答案为 \(F(a)\),则有 \(\frac{F(a)+F(b)}{2}\ge F(\frac{a+b}{2})\),所以 \(F(x)\) 是下凸的,可以三分 \(x_n\) 的取值。
时间复杂度 \(O(n\log n\log{\sum a_i})\),空间复杂度 \(O(n)\)。
14.Gym102331H Honorable Mention
设 \((f,v)\) 表示容量为 \(f\),费用为 \(v\) 的边。先建出费用流的图:源点向 \(0\sim n\) 连 \((1,0)\) 的边,\(i(0\le i\lt n)\) 向 \(i+1\) 连 \((1,a_{i+1})\) 的边,\(0\sim n\) 向汇点连 \((1,0)\) 的边,跑流量为 \(k\) 的最大费用流。设 \([l,r]\) 内选出 \(x\) 个不交非空子区间的答案为 \(f(l,r,x)\),则 \(f(l,r,x)\) 关于 \(x\) 是上凸的。
建一棵线段树,对于每个区间 \([l,r]\) 分别维护 \(l\rightarrow l+1\) 流量为 \(0/1\),\(r-1\rightarrow r\) 流量为 \(0/1\) 时 \((x,f(l,r,x))\) 组成的 \(4\) 个凸包,这可以用 \(2\times 2\) 的矩阵表示。合并时做「矩阵乘法」,但矩阵乘是凸包做闵可夫斯基和,矩阵加是凸包取 \(\min\),特别地,在做左区间最右端流量为 \(1\) 和右区间最左端流量为 \(1\) 的凸包的闵可夫斯基和后,还要将所得凸包向左平移一位(因为合并后少了一个区间)。由于本题的特殊性,矩阵乘法得到的 \(4\) 个函数一定都还是凸包。这部分复杂度是 \(O(n\log n)\) 的。
考虑如何查询 \(f(l,r,k)\)。首先要在线段树上定位出 \([l,r]\) 对应的 \(O(\log n)\) 个区间,但由于无法直接合并,所以考虑 wqs 二分。具体地,二分每选出一个区间就要花费 \(c\) 的代价,相当于在每个凸包上找到斜率为 \(c\) 的直线与凸包的切点,进而求出最多能选出多少个区间,这样单次询问是 \(O(\log \sum|a|\log^2 n)\) 的。利用类似整体二分的思想,每次先将询问排好序挂到对应区间上,然后双指针求答案,二分内层所有询问的时间复杂度就降到了 \(O(q\log n)\)。
总时间复杂度 \(O(q\log\sum|a|\log n)\),空间复杂度 \(O((n+q)\log n)\)。
15.Gym102482C Conquer the World
没讲。
16.Gym102331J Jiry Matchings
没讲。
线性规划及其对偶问题
有一家工厂,生产 \(n\) 种物品,这 \(n\) 种物品都由 \(m\) 种原材料组成,其中第 \(i\) 种物品由 \(A_{i,1}\) 个原材料 \(1\)、\(\cdots\)、\(A_{i,m}\) 个原材料 \(m\) 组成。商家希望第 \(i\) 种物品的利润至少为 \(C_i\),买家希望购入的物品含有原材料 \(i\) 的个数不超过 \(B_i\)。
买家希望花尽量少的钱,即第 \(i\) 种物品的利润恰好为 \(C_i\),在此基础上还希望购入的物品含有原材料 \(i\) 的个数不超过 \(B_i\),那么商家的最大利润是多少?
假设最终第 \(i\) 种物品卖出了 \(x_i\) 件。限制:\(\forall 1\le i\le m\),\(\sum_{j=1}^{n}A_{j,i}x_j\le B_i\);\(\forall 1\le i\le n\),\(x_i\ge 0\)。即要求最大化 \(S=\sum_{i=1}^n C_i x_i\)。
商家希望卖尽量多的钱,即卖出的物品含有原材料 \(i\) 的个数恰好为 \(B_i\),在此基础上还希望第 \(i\) 种物品的利润至少为 \(C_i\),那么买家的最少花费是多少?
假设最终第 \(i\) 种原材料需要的价格为 \(y_i\)。限制:\(\forall 1\le i\le n\),\(\sum_{j=1}^{m}A_{i,j}y_j\ge C_i\);\(\forall 1\le i\le m\),\(y_i\ge 0\)。即要求最小化 \(T=\sum_{i=1}^m B_i y_i\)。
强对偶定理:\(\max S=\min T\)。根据上面的组合意义这两者也确实相等。
应用:二分图最大权匹配、最大费用循环流模型、最大流最小割定理,具体见此文。
17.CF1307G Cow and Exercise
如果要求 \(1\) 到 \(n\) 的最短路至少是 \(\lambda\),那么所有边权的总增量最少是多少?设 \(d_i\) 表示 \(1\) 到 \(i\) 的最短路长度,\(w(i,j)\) 表示 \(i\rightarrow j\) 的边的长度,\(x(i,j)\) 表示 \(i\rightarrow j\) 的边的长度需要的增量。限制:\(\lambda\le d_n-d_1\),\(d_v\le d_u+w(u,v)+x(u,v)\),\(x(i,j)\le 0\)。即最小化 \(\max(\lambda-d_n+d_1,0)\inf+\sum_{(u,v)}\max(-w(u,v)-d_u+d_v,0)\)。
发现这是最大费用循环流的对偶问题。设 \((f,v)\) 表示容量为 \(f\),费用为 \(v\) 的边。建出费用流的图:\(n\) 向 \(1\) 连 \((\inf,\lambda)\) 的边,\(u\) 向 \(v\) 连 \((1,-w(u,v))\) 的边。跑最大费用循环流即为答案。实际上,流经 \(n\rightarrow 1\)、容量为 \(\inf\) 的边的流量至多为 \(n\),枚举该边流量 \(k\),删去该边,问题变成了求源点为 \(1\),汇点为 \(n\),流量恰好为 \(k\) 的最大费用流。注意到这与 \(\lambda\) 无关,设其为 \(f_k\),可以通过每次增广 \(1\) 点流量在 \(O(n^2m)\) 时间内预处理出 \(f_0\sim f_n\),答案即为 \(\max_{k=0}^n f_k+k\lambda\)。
\(k=0\) 的情况平凡。如何快速计算 \(\max_{k=1}^n f_k+k\lambda\)?一种想法是 \(\max_{k=1}^n f_k+k\lambda\le x\) 等价于 \(\max_{k=1}^n \frac{f_k+k\lambda-x}{k}\le 0\),进而 \(\lambda\le \min_{k=1}^n \frac{x-f_k}{k}\),可以单次 \(O(n)\) 求解 \(\lambda\) 的最大值。另一种想法是考虑函数 \(F_k(\lambda)=f_k+k\lambda\),什么时候 \(F_k(\lambda)\ge F_{k-1}(\lambda)\),当且仅当 \(\lambda\ge f_{k-1}-f_k\)。结合 \(f\) 是上凸的可知当 \(\lambda\in[f_{k-1}-f_k,f_{k}-f_{k+1}]\) 时 \(\max_{i=1}^n f_i+i\lambda=F_k(\lambda)\),所以单次询问可以二分做到 \(O(\log n)\) 的复杂度。
总时间复杂度 \(O(n^2m+qn)\) 或 \(O(n^2m+q\log n)\),空间复杂度 \(O(n+m)\)。
18.P6631 [ZJOI2020] 序列
设操作 \(1\) 会使 \(a_i\) 减少 \(h_i\),则操作 \(1\) 的代价为 \(\sum_{i=1}^{n+1}\max(h_i-h_{i-1},0)\),之后操作 \(2,3\) 就独立了,代价为 \(\sum_{i=1}^{n+2}\max((a_{\max(i-2,0)}-h_{\max(i-2,0)})-(a_{\min(i,n+1)}-h_{\min(i,n+1)}))=\sum_{i=1}^{n+2}\max((a_{\max(i-2,0)}-a_{\min(i,n+1)})-h_{\max(i-2,0)}+h_{\min(i,n+1)})\)。
发现这是最大费用循环流的对偶问题。建出费用流的图,只有距离不超过 \(2\) 的点有从小向大连边,且最大流不超过 \(3\),因此可以设 \(f_{i,0/1/2,0/1/2}\) 表示第 \(i-1\) 个点剩余出流为 \(0/1/2\),第 \(i\) 个点剩余出流为 \(0/1/2\),最小费用。转移是 \(O(1)\) 的。
时间复杂度 \(O(n)\),空间复杂度 \(O(n)\)。