网络流建模总结(待更)

网络流建模总结

默认 \(s,t\) 为源点、汇点。

I 二分图

基本二分图最大匹配建模方法:

对于所有左部点 \(i\),连 \((s,i,1)\);对于所有右部点 \(j\),连 \((j,t,1)\);对于二分图中所有边 \((i,j)\),连 \((i,j,1)\)。跑最大流。

一些经典结论

二分图最大匹配 = 二分图最小点覆盖 = 总点数 - 二分图最大独立集

最大团 = 补图最大独立集

P4251

二分答案 \(mid\),判定条件为「只考虑 \(a_{i,j}\le mid\) 的点,能否选出 \(n-k+1\) 个点」。将行和列分别当成左部点和右部点,对于所有 \(a_{i,j}\le mid\),我们连接行 \(i\) 和列 \(j\),这样形成了一个二分图,不难发现此时能最多选出的点数即为二分图的最大匹配。

P2402

与上一题基本一致,注意这里源点向其它点连边的边权是 \(s_i\),其它点连向汇点的边权是 \(p_i\)。二分图中间连的边是 \(i\)\(j\) 在原图中的最短路,跑一遍 floyd 即可。

ABC274G

不难发现我们需要求的是一个类似于最小点覆盖的东西,我们将所有行与列的极大连续段相同编号,于是问题转换成二分图最小点覆盖。

II 拆点

对点有限制时,我们通常将一个点拆成两个点,在中间连边,边权为点的限制。在表示一个点所具有不同的状态时,我们也通常会拆成若干个点。

P2891

我们的建模中应该同时存在食物、饮料、牛,这是因为每头牛只能吃固定量的食物和饮料。于是我们考虑这么建模:对于所有食物 \(i\),连 \((s,i,1)\);对于所有饮料 \(j\),连 \((j,t,1)\);对于所有牛 \(k\) 以及它喜欢的食物 \(f\),饮料 \(d\),连 \((f,k,1),(k,d,1)\)

当然这样还是不对的,因为我们还是无法保证流入牛 \(k\) 的流量至多为 \(1\)。对牛所在的点有限制,考虑拆点。我们将牛 \(k\) 拆成牛左部点 \(k_1\) 和牛右部点 \(k_2\),并连 \((k_1,k_2,1)\),将原来的连边改为 \((f,k_1,1)(k_2,d,1)\) 即可。

P3153

二分答案,如果没有限制的话,就是一个二分图最大匹配模型。考虑如何处理「至多和 \(k\) 个不喜欢的人匹配」。

我们将一个人的两种状态拆成两个点,「喜欢」和「不喜欢」。对于一对互相喜欢的 \((i,j)\),用 \(i\) 的「喜欢」连 \(j\) 的「喜欢」,否则用 \(i\) 的「不喜欢」连 \(j\) 的「不喜欢」,边权为 \(1\);一个人的「喜欢」和「不喜欢」之间连边权为 \(k\) 的边;源点连「喜欢」,汇点连「不喜欢」,边权为 \(mid\)

判定条件为是否满流,即最大流是否为 \(n\times mid\)

P2764

将划分出的若干路径刻画为若干条链,注意到链数等于 \(m\) 减去所有链的长度之和,因此问题转换成最大化选中的边。此时限制为,一个点的入度、出度至多为 \(1\)(我们将选中一条边 \((u,v)\) 视为对 \(u,v\) 作度数覆盖)。将一个点的两种状态拆成两个点,「入度」和「出度」。对于一条边 \((u,v)\),用「出度」\(u\) 连「入度」\(v\);源点连「出度」,汇点连「入度」即可。直接就是一个二分图最大匹配。

III 二选一

若每个点有两种决策,可以将 \(s\) 刻画为其中一个决策,\(t\) 刻画为另一个决策,跑最小割。

最小割连边技巧 1:考虑若 \((s,u)\) 这条边断了,则 \(u\)\(t\) 连通,此时 \(u\) 的决策为 \(t\) 所代表的决策,这种决策将会带来什么代价,这个代价就是 \((s,u)\) 的边权。

最小割连边技巧 2:若我们钦定一些边不能被割掉,直接将这些边的边权设为无穷大即可。

P2774

并非二选一模型但是放在这里比较合适。

对于最大化总收益的题目,我们一般考虑拿理想情况下能获得的最大收益减去最小的实际会消耗的代价。计算这个最小代价就是最小割。

不难发现如果我们按照 \((i+j)\bmod2\) 染色的话,原图可以转换成一个二分图,那么对于一对相邻的黑白点,我们直接连边,边权设为无穷大。对于黑点,连边 \((s,(i,j),val_{i,j})\);对于白点,连边 \(((i,j),t,val_{i,j})\)。拿 \(\sum val_{i,j}\) 减去最小割就是答案。

P1791

还是假定能获得最大收益,考虑最小化消耗代价。这里的两种决策即为「雇」和「不雇」,分别令 \(s,t\) 代表这两种决策。

对于所有 \(i\),连边 \((s,i,\sum\limits_{j=1}^nE_{i,j})\),连边 \((i,t,a_i)\);对于所有 \((i,j)\),连边 \((i,j,2\times E_{i,j})\)。最后这种连边代表如果 \(i\) 被雇、\(j\) 没被雇,则要强制割掉这条边,这样会带来 \(2\times E_{i,j}\) 的损失,也即 \(E_{i,j}-2\times E_{i,j}=-E_{i,j}\)。跑最小割即可。

Trick1(建虚点):对于类似于「若 \(i_1,i_2,\dots,i_k\) 同时选择决策 \(x\),那么将会获得 \(p\) 的额外收入」的限制,刻画为「若这些点中存在一个不选择决策 \(x\) 的点,将消耗 \(p\) 的代价」。建立虚点 \(j\),将 \(j\) 连向 \(i_!,i_2,\dots,i_k\) 后将 \(s\) 连向 \(j\),或者反着来。第一种连边的边权是无穷大,因为我们要绑定这种关系,第二种连边的边权就是无穷大。

Trick2(切糕模型):对于多选一问题,将值域刻画成一条链,\(s\) 分别连向值域为 \(1\) 的位置,值域为 \(\max\) 的位置分别连向 \(t\)。接着根据相关问题刻画即可。

类似题目:P4313、P1646、P3973、P3227

IV 最大权闭合子图

最大权闭合子图的定义是,从原图中选一个点集,满足若选择了 \(u\),则对于所有 \((u,v)\in E\)\(v\) 都必须被选中。要求最大化点权和。注意这里点权可正可负,所以一般看到收益和代价同时出现你就赢了。

考虑这个东西怎么建模,假定能获得最大收益,把所有正点权加起来,将正点权刻画为「收益」、负点权刻画为「代价」。然后直接按「二选一」方法最小割即可。具体来说,对于所有 \(a_i>0\),连边 \((s,i,a_i)\);对于所有 \(a_i<0\),连边 \((i,t,-a_i)\);对于所有边,连边 \((u,v,\inf)\)

P4174

我们不考虑两个点之间建图,而是考虑将一个用户刻画成一个点,令这个点向两个塔连边。问题转换成最大权闭合子图。

若干倍经验:P3410、P2762

VI 杂题

ARC107F

\(\sum \operatorname{abs}(\sum B_i)\) 比较难处理,考虑拆贡献,钦定最终每个 \(B_i\) 被贡献了 \(\delta_i\) 次,其中 \(\delta_i\in \{-1,0,1\}\)。需要注意到一个连通块内的 \(\delta_i\) 相同,这样我们就可以将和的绝对值刻画为 \(\delta_i\) 的三种决策,然后就可以最小割了。

假设我们可以获得总贡献 \(\sum\operatorname{abs}(B_i)\),考虑减去最小消耗代价。把每个点拆点,结合 \(s,t\) 我们就可以刻画三种决策了。对于原图中的边,注意到相邻两点不能取不同的 \(\delta_i\),所以我们将 \(u\)\(v'\)\(u'\)\(v\) 连边权为无穷大的边。对于 \(B_i>0\),连边 \((s,i,2\times B_i)\);否则连边 \((i',t,2\times \operatorname{abs}(B_i))\)。对于 \(i\)\(i'\),连边 \((i,n+i,A_i+\operatorname{abs}(B_i))\)。直接跑即可。

P3749 [六省联考 2017] 寿司餐厅

题目限制等价于,选择若干区间满足不存在子集关系,你的收益就是被区间覆盖到的子区间的 \(d_{i,j}\) 的和,代价就是被覆盖的所有点的那个 \(mx^2+cx\)。注意到若你选择了区间 \((i,j)\),则你必定要加上 \((i,j)\) 的所有子区间 \((k,l)\) 的收益,以及区间内每个单点的代价。考虑将限制刻画为最大权闭合子图。

对于所有 \(i\le k\le l\le j\),连边 \(((i,j),(k,l))\),其中 \((i,j)\) 的点权为 \(d_{i,j}\);对于所有 \((i,i)\),连边 \(((i,i),i)\)\(i\) 单点的点权为 \(-a_i\),代表你每选一种点你的损失。接着考虑如何刻画 \(mx^2\),因为要求只有在 \(x\) 被选了的情况下才能算入 \(mx^2\) 的代价,因此我们考虑建虚点,只要有一个所属的被选了,这种 \(x\) 就得被选。对于所有 \(i\),连边 \((i,a_i')\)\(a_i'\) 的点权为 \(ma_i'^2\)。直接跑最大权闭合子图即可。

无法通过最后两个点,经过仔细分析发现连所有子区间太过于冗余,不难发现只需要连接区间的所有前后缀,这是因为子区间可以直接刻画为前缀区间的后缀区间。因此边数降低了一维,可以通过。

CF1666 Kingdom Partition

起因是 flama 大神讲课时有人提到了这个题。这个题有一个对最小割具有深刻启示作用的做法,我们后面再说,先来展示一下主播的做法。

神秘的做法

一个点有三个状态,这很不最小割,考虑如何刻画成两个集合。我一开始的想法是,把每个点拆成三个点 \((u,0/1/2)\),代表 \([u\in A/B/C]\) 这个布尔变量,但随即发现连边的限制长成这样:若 \((u,0)\in S\),且 \((u,1)\)\((u,2)\) 都属于 \(T\),则有代价 \(2w\)。与运算也太难处理了,我们无法控制两个点都没割 \(T\),于是倒闭了。

但是我们真的倒闭了吗?发现我们是会或运算的,所以想办法往上靠吧。注意到如果我们将原题的无向边,当成两条有向边来看待,即拆成两条「若 \(u\in A,v\in A\),则消耗 \(w\) 代价」的边,那实际上两端点都为 \(A/B\) 与一端点为 \(C\) 消耗的代价就一样了!我们就不用把这两个东西分开看待了。再次修改状态,令 \((u,0/1)\) 分别代表 \([u\in A]\vee [u\in C]\),以及 \([u\in B]\vee [u\in C]\)。对于原图的边 \((u,v,w)\),我们分别连 \(\Big((u,0),(v,1),w\Big),\Big((u,1),(v,0),w\Big),\Big((v,0),(u,1),w\Big),\Big((v,1),(u,0),w\Big)\) 四条边即可,代表若 \(u\)\(A/C\)\(v\) 不选 \(B/C\)(即选 \(A\))有 \(w\) 的代价;若 \(u\)\(B/C\)\(v\) 不选 \(A/C\)(即选 \(B\))有 \(w\) 的代价;将 \(u,v\) 反过来同理。对于另一种限制 \(a\in A,b\in B\),直接连 \(\Big(s,(a,0),\text{inf}\Big),\Big(s,(b,1),\text{inf}\Big),\Big((a,1),t,\text{inf}\Big),\Big((b,0),t,\text{inf}\Big)\) 即可,代表如果这么选你会万劫不复。

看起来很美好,但是会发现还有一个 case,即当 \((u,0),(u,1)\) 属于同一个集合时怎么处理。如果此时 \(u\in C\) 是合理的,但如果出现 \([u\in A]\wedge [u\in B]\) 的情况就不对了,我们的建模中并没有判掉这种情况。但当我们将这种情况代入上面的连边时,发现实际上这种点与 \(C\) 集合中的点的消耗是相同的,因此我们可以把这种矛盾的点当成 \(u\in C\),并没有问题。构造方案的话,就从 \(s\) 开始,在残量网络上搜,每次只经过没被割的边即可。这样搜到的状态的布尔值就是一。对于点 \(u\),若 \((u,0/1)\) 中只有一个被搜到过就输出对应的那个集合,否则输出 \(C\) 即可。

下面展示更具有启发意义的做法。

不神秘的做法

最小割的另一种表达方式是,你有若干个布尔变量 \(x_1,x_2,\dots,x_n\),还有若干限制 \((u,v,w)\) 形如「若 \(x_u=1,x_v=0\),则消耗 \(w\) 的代价」,要给这 \(n\) 个变量赋值并最小化总代价 \(\sum\limits_{(u,v,w)\in E}wx_u(1-x_v)\)。考虑将每个点只拆成两个状态 \(x_A,x_B\),代表 \([x\in A]\)\([x\in B]\) 两个变量,这样 \([x\in C]\) 就可以表示成 \(1-x_A-x_B\)。根据上式,重新写一下本题的式子:

\[\sum\limits_{(u,v,w)\in E}2wx_{u,A}x_{v,A}+2wx_{u,B}x_{v,B}+wx_{u,A/B}(1-x_{v,A}-x_{v,B})+wx_{v,A/B}(1-x_{u,A}-x_{u,B}) \]

这非常不像最小割,考虑通过移项让其变成最小割的形式。有:

\[\sum\limits_{(u,v,w)\in E}wx_{u,A}(1-x_{v,B})+wx_{u,B}(1-x_{v,A})+wx_{v,A}(1-x_{u,B})+wx_{v,B}(1-x_{u,A}) \]

这很最小割。直接根据式子反推回建模即可。但会发现还有一个 case,即当 \(x_{u,A}=x_{v,A}=1\) 时如何处理。考虑这种点在式子中的贡献,将 \(A/B/C\) 三类点以及这种点作为边的另一端点带进上式,发现贡献分别为 \((w,w,0,0)\),这与 \(C\) 类点的贡献一模一样!因此我们不必再考虑这种点,并没有问题。

两种做法的建模是一样的,你可以看作第一种做法是在为第二种做法的 \(x_{u,A/B}\) 找「组合意义」。在遇到类似的 \(0/1\) 赋值题目时,可以考虑第二种做法用式子套上最小割。

posted @ 2025-08-19 13:16  NagasakiSoyo  阅读(34)  评论(0)    收藏  举报