模拟费用流(一):关键点
recall 一下费用流的一些结论:
- 如果只要求最大流,任意顺序加边, 在残量网络上接着增广,直到不存在增广路,求出的流都是最大流。
- 如果要删边 \((u,v)\) 或者改流量,跑 \(t\to v\to u\to s\) 的退流。
- 使用 SSP 算法每次找一条增广路,如果初始图中没有负环,则任意时刻图中均无负环。
- 任意求一个最大流,得到一个残量网络;如果残量网络中存在负环,我们直接把这个负环整个增广(这个操作不会改变流量),直到没有负环。这样求出的流也是最小费用最大流。
关键点
QOJ7185
给定一个二分图,左边有 \(n\) 个点,右边有 \(m\) 个点,右边每个点有容量,左边第 \(i\) 个点和右边第 \(j\) 个点之间的边权为 \(c_{i,j}\)。对每个 \(k=1,2,\cdots,n\),求流量为 \(k\) 的最小费用流。
\(1\le n\le 50000,1\le m\le 10,1\le c_{i,j}\le 10^9\)。
这题和反悔贪心什么没有关系,但是这一类的许多模拟费用流问题最后都会归结到类似这个的模型上。
因此,我们先介绍解决这个问题的快速算法。
首先建出费用流图,把 \(s,t\) 和右边的 \(m\) 个点称作关键点。
考虑维护每两个关键点之间不经过其他关键点的可能路径集合,这样每次我们在增广时如果要求出 \(s\to t\) 的最短路,只需要在关键点之间跑最短路。
考虑得到一个增广路之后如何模拟增广,注意到我们不需要考虑和 \(s,t\) 相关的反向边,因此关键点之间不经过其他关键点的最短路形态实际上相当简单,本质上只有以下几种:
- \(s\) 到某个右部点 \(R_j\):经过某个还未匹配的 \(L_i\),路径形如 \(s\to L_i\to R_j\)。
- 右部点之间:\(R_j\to L_i\to R_k\)。这里一定只会经过一个左部点,因为不能经过别的右部点。
- 右部点到 \(t\):直接走 \(R_j\to t\)。
我们可以在每个左部点 \(L_i\) 处把经过 \(L_i\) 的路径的贡献算进去。
由于我们找到的最短路的长度也是 \(O(m)\) 级别,对这条最短路经过的左部点重新计算它们的贡献即可。
求最短路每次需要 \(O(m^2\log n)\) 建边,然后 \(O(m^3)\) 求解最短路;重新计算左部点贡献时,每个左部点最多只有两条邻边会翻转,只会影响 \(O(m)\) 种决策。一共只有 \(O(m)\) 个左部点,故这部分复杂度也是 \(O(m^2\log n)\)。
综上,本题在 \(O(n(m^2\log n+m^3))\) 时间内解决。
不难发现,我们也可以在 \(O(m^2\log n+m^3)\) 时间内完成加边/删边,退流以及消圈等操作。
AGC018C Coins
反悔贪心可以导出一个做法。考虑建图跑费用流:
左边建 \(n\) 个点 \(P_1,P_2,\cdots,P_N\),连边 \(s\to P_i\),边权 \(0\) 容量 \(1\)。
右边建三个点 \(A,B,C\),都连到 \(t\),边权 \(0\) 容量分别为 \(X,Y,Z\)。
每个 \(P_i\) 连三条边 \(P_i\to A,B,C\),边权分别为 \(a_i,b_i,c_i\),容量为 \(1\)。
于是就变成了 QOJ7185,套过来就行。这里 \(n\le 10^5,m\le 3\)。
https://atcoder.jp/contests/agc018/submissions/52902728
[NOI2019] 序列
每个点有四种决策:两边都不选,\(a\) 那边选,\(b\) 那边选,\(a,b\) 同时选。
对后三种决策建出三个点 \(Q_{1\cdots 3}\),但是我们发现没办法直接确定某个 \(Q_i\to t\) 的流量。
具体来说我们实际的约束是:
- \(Q_3\to t\) 的流量 \(\ge L\);
- \(Q_1\to t,Q_3\to t\) 的流量之和为 \(K\);
- \(Q_2\to t,Q_3\to t\) 的流量之和为 \(K\)。
朴素的想法是枚举 \(Q_3\to t\) 的流量 \(d\ge L\),可以得到 \(Q_1,Q_2\to t\) 的流量均为 \(K-d\),然后跑 QOJ7185。
但是每次跑一遍复杂度至少为平方,考虑 \(d\) 每增加 \(1\),相当于我们要进行两次退流 \(t\to Q_1\to s,t\to Q_2\to s\),再进行一次增广 \(s\to Q_3\to t\)。对于增广我们正常做,对于退流改成求 \(t\to s\) 的最长路即可。
此时由于我们反过来要求 \(t\to s\) 的最长路,还需要额外维护 \(Q_i\to s\) 的最长路。
总复杂度仍然是 \(O(n\log n)\)。 这个做法的常数有点大...不太能过的样子QAQ
AGC034D Manhattan Max Matching
设 \(M\) 为红球总数。考虑把 \(|x_i-x_j|+|y_i-y_j|\) 拆成
那么会得到四种符号,我们在中间建四个点分别表示 \((+,+),(+,-),(-,+),(-,-)\) 四种符号。
接下来对每个红球 \(i\) 我们都连向中间四个点,边权分别为 \(x_i+y_i,x_i-y_i,-x_i+y_i,-x_i-y_i\);然后另一边的每个蓝球 \(i\) 我们也从中间四个点连到他,边权分别为 \(-x_i-y_i,-x_i+y_i,x_i-y_i,x_i+y_i\)。
那么这个问题就变成和 QOJ7185 几乎一样的形式了,只不过此时是中间有四个点,左右两侧各有 \(M\) 个点。类似地维护中间四个点 \(Q_1,Q_2,Q_3,Q_4\) 它们 \(Q_i\to Q_j\) 的最短路,然后再维护 \(s\to Q_i,Q_i\to t\) 的最短路即可。
时间复杂度:\(O(M\log M)\) 带很大常数。
[SD2024 一轮省集] Circuits - By alpha1022
二维平面上有 \(n+m\) 个点 \((x_1,y_1),(x_2,y_2),\cdots,(x_n,y_n)\) 和 \((a_1,b_1),(a_2,b_2),\cdots,(a_m,b_m)\)。
现在所有的 \((x_i,y_i)\)(\(1\le i\le n\))已经按照 \(1,2,\cdots,n\) 的顺序连成一个环。现在你可以选择 \(k\) 个 \((a_j,b_j)\) 和环上的 \(k\) 条边,把你选的 \((a_j,b_j)\) 按照任意顺序分别插入到这 \(k\) 条边的中间。这里每条边里面至多插入一个 \((a_j,b_j)\),每个 \((a_j,b_j)\) 最多被选中一次。
在做完上述操作后会得到一个 \(n+k\) 个点的环,定义该方案的分数为所有边的两端点的曼哈顿距离之和。此外,如果选中了 \((a_j,b_j)\),分数还会额外加上 \(w_j\)。你希望最大化这个方案的分数。
你需要对 \(k=1,2,\cdots,n\) 求出上述问题的答案。
\(1\le n\le m\le 10^5,-10^8\le a_i,b_i,x_i,y_i,w_i\le 10^8\)。
考虑一个点 \((a_i,b_i)\) 和一条边匹配,权值为
这里根据 \(a_i\) 和这两个 \(x\) 的大小关系,以及 \(b_i\) 和这两个 \(y\) 的大小关系,可以拆出来 \(3\times 3=9\) 个点。
接下来类似上题进行建图即可。复杂度 \(O((n+m)\log (n+m))\) 带很大常数。
[2022 ICPC 杭州区域赛] H. RPG Pro League
你在玩一个游戏,这个游戏中有三类角色:输出位,增益位,生存位。
一个队伍由四个角色构成,每个队伍必须形如:
- 两个输出位,一个增益位,一个生存位。
- 一个输出位,两个增益位,一个生存位。
现在有 \(n\) 个角色,第 \(i\) 个角色有一个可以担任的位置集合 \(S_i\subseteq\{输出,生存,增益\}\),让这个角色加入队伍的代价为 \(a_i\)。你希望组出最多的队伍数量,在此基础上求出最小的组队代价。一个角色只能加入至多一个队伍,且一个角色同时只能作为一个队伍中的一个位置。
有 \(q\) 次修改,每次给出 \(x,v\),表示将 \(a_x\leftarrow v\)。每次修改后你都需要求出上述问题的答案。
\(1\le n,q\le 10^5,1\le a_i\le 10^9\)。
解法一(官方做法)
考虑先算出最多能组多少队,然后再算出最小代价。把三种角色称为 A,B,C
类角色。
建一张图,左边有 \(4\) 个点分别代表 \(\{A\},\{B\},\{C\},\{A,B\}\),右侧七个点分别代表 \(A,B,C\) 的任意非空子集。右侧点 \(T\) 的点权就是所有 \(i\) 里面 \(S_i=T\) 的 \(i\) 的个数,对于左侧点 \(U\) 和右侧点 \(V\),如果 \(U\cap V\neq\varnothing\) 就连边。
现在相当于求这个二分图的多重最大匹配。
我们知道由 Hall 定理,存在 \(k\) 重完美匹配当且仅当 \(\forall S,|N(S)|\ge k|S|\)。于是答案就是
考虑如何算最小代价,按照权值从大到小依次考虑每个数,如果能删除他就删除。这里容易用贪心解释,也可以用拟阵来解释。那么修改的时候可能会删除一个数,插入一个数。类似人员调度那题进行维护即可。
解法二(我的做法)
可以看到《[NOI2019] 序列》和《RPG Pro League》分别给出了退流 和 两种操作,这个模拟费用流能做的操作实际上是很多的。