网络流建模例题

例 1:[ABC285G] Tatami

给定 \(n\times m\) 的矩阵,每个位置为 \(1/2/?\),要用 \(1\times 1\)\(1\times 2\)(可以选择)的单元覆盖整个矩形,满足 \(1\) 位置只能被 \(1\times 1\) 的覆盖,\(2\) 位置只能被 \(1\times 2\) 的覆盖,\(?\)位置任意,判断是否存在合法方案,\(n,m\le300\)

相当于用 \(1\times 2\) 的单元覆盖所有 \(2\) 位置,且不能覆盖 \(1\) 位置

将矩阵黑白染色,分为两部分,相邻的非 \(1\) 位置之间连边,则转化为判断二分图是否存在一种匹配,满足所有的 \(2\) 都被匹配了

无法直接求,但是若将 \(?\) 位置之间两两连边,并将左右点数补成相同(补的点看做 \(?\)),则转化为判断是否存在完美匹配

但是直接两两连边边数为 \(O((nm)^2)\)

可以在中间增加一个点,左右都和其连边

总时间复杂度 \(O(nm\sqrt{nm})\)

代码

例 2:CF708D Incorrect Flow

给定一张 \(n\)\(m\) 边的有源汇网络,每次可以花 \(1\) 的代价使某条边的流量 \(f\) 或容量 \(c\) 加减一,求要使其合法,最少需要花费的代价,\(n,m\le100,c,f\le10^6\)

对于原图的边 \((u,v,c,f)\),首先需要 \(u\)\(v\) 连容量上下界都是 \(f\),费用为 \(0\) 的边,然后考虑连修改的边:

  • \(f\le c\),则
    • 可以花 \(1\) 的代价使流量减小,相当于从 \(v\)\(u\) 退流,且最多减小 \(c\) 次,因此 \(v\)\(u\) 连容量上界为 \(f\),费用为 \(1\) 的边
    • 可以花 \(1\) 的代价增大流量,最多增加 \(f-c\) 次,从 \(u\)\(v\) 连容量上界为 \(f-c\),费用为 \(1\) 的边
    • 流量等于 \(c\) 后,可以花 \(2\) 的代价使容量和流量都加一,因此 \(u\)\(v\) 连容量上界 \(\infty\),费用为 \(2\) 的边(显然最小费用最大流会优先选择费用小的边,因此不用考虑和前一种冲突)
  • \(f>c\),则至少需要花 \(f-c\) 的代价令 \(f=c\),因此\(f-c\) 先计入总答案
    • 此时的 \(f\)\([c,f]\) 的范围内,即在流量等于 \(f\) 的基础上,可以令流量免费减少不超过 \(f-c\),因此 \(v\)\(u\) 连容量为 \(f-c\),费用为 \(0\) 的边
    • 然后可以花 \(1\) 的代价继续减小,从 \(v\)\(u\) 连容量为 \(c\),费用为 \(1\) 的边(同样会优先选择上一种,不需要考虑冲突)
    • 或者花 \(2\) 的代价加一(显然最优解不会先减少再增加),\(u\)\(v\) 连容量为 \(\infty\),费用为 \(2\) 的边

然后跑有源汇上下界最小费用可行流即可

时间复杂度 \(\def\la{\langle}\def\ra{\rangle} O(\la N\ra \la M\ra \la F\ra)=O(n(n+m)mv)\),但基本卡不满

代码

例 3:[ABC239G] Builder Takahashi

求图的最小割(点),\(n\le 100\)

拆点,原本的点 \(i\) 拆为 \(i\)\(i+n\),其中 \(i\) 为入点,\(i+n\) 为出点,\(i\)\(i+n\) 连边,边权为删去点 \(i\) 的代价;原图的边 \(u-v\) 在新图上连 \(u-(v+n)\)\(v-(u+n)\),边权为无穷大;然后求新图上 \(n+1\)\(n\) 的最小割即可

时间复杂度 \(O(n^2m)\)

代码

例 4:[ABC274G] Security Camera 3

\(n\times m\) 的网格,一部分位置有障碍物,可以放置监控(一个位置可以放置多个),一个监控可以覆盖它正方向(四个方向之一)的所有位置(包括自己的位置,但不能穿越障碍物),求覆盖所有无障碍位置所需的最小监控数量,\(n,m\le300\)

对于每行和每列,分别求出所有极长连续无障碍子段。显然一个这样的子段最多放置一个监控

对于位置 \((i,j)\),显然它所在的行极长连续无障碍子段列极长连续无障碍子段中,至少一个需要放置监控

因此在两者之间连边,求出得到的二分图的最小边覆盖即可

时间复杂度 \(O(nm\sqrt {nm})\)

代码

例 5:[ABC317G] Rearranging

\(n\)\(m\) 列的矩阵(\(1\sim n\) 每个数恰好出现 \(m\) 次),可以重排每一行,使得最后得到的矩阵每一列都是 \(1\sim n\) 的排列,求是否存在方案并给出具体方案,\(n,m\le100\)

建立 \(n\) 个左部点分别表示每一行,建立 \(n\) 个右部点分别表示每种值,对于每个位置在它所在行对应的点和它的值对应的点之间连边

则相当于在得到的图上求 \(m\) 次完美匹配,且每次用的边不能重复

每次将匹配过的点删去并重置源点到左部点、右部点到汇点的边即可

时间复杂度 \(O(m\cdot mn\cdot \sqrt n)=O(m^2n^{3/2})\)

代码

例 6:[AGC034D] Manhattan Max Matching

\((RX_i,RY_i)\) 上有 \(RC_i\) 个红点,\((BX_i,BY_i)\) 上有 \(BC_i\) 个蓝点,其中 \(1\le i\le n\),满足 \(\sum RC_i=\sum BC_i\)。要将其配对,配对的价值为两个点的曼哈顿距离,求最大价值。\(n\le1000,RC_i,BC_i\le10,RX_i,RY_i,BX_i,BY_i\le10^9\)

\((x_1,y_1)\)\((x_2,y_2)\) 之间的曼哈顿距离为

\[\begin{aligned} &|x_1-x_2|+|y_1-y_2|\\ =&\max(x_1-x_2,x_2-x_1)+\max(y_1-y_2,y_2-y_1)\\ =&\max(x_1-x_2+y_1-y_2,x_1-x_2+y_2-y_1,x_2-x_1+y_1-y_2,x_2-x_1+y_2-y_1)\\ =&\max((x_1+y_1)+(-x_2-y_2),(x_1-y_1)+(-x_2+y_2),(-x_1+y_1)+(x_2-y_2),(-x_1-y_1)+(x_2+y_2))\\ \end{aligned}\]

于是红点作为左部点,蓝点作为右部点,中间建立四个虚点,左右分别和其连边(注意顺序),求多重最大权匹配即可(显然求最大权匹配时,会选四条边种最大的一个)

理论时间复杂度为 \(O(n^2f)\),但实际跑不满

代码

例 7:P6062 [USACO05JAN] Muddy Fields G

基本和 [ABC274G] Security Camera 3 相同

代码

例 8:CF1404E Bricks

类似 P6062 [USACO05JAN] Muddy Fields G,但是区域不能重叠,求最少数量,\(n,m\le200\)

定义分割线为分割两个向邻的可放置格子的线,定义选择分割线为最终方案中此分割线两侧分属不同区域,定义分割线相邻当且仅当两者有公共点

显然相邻的一对分割线中至少选择一个

相邻分割线中一定是一个横向,一个纵向

因此建立二分图,横向分割线对应左部点,纵向对应右部点,两线相邻则连边

由于最终区域数量要最少,因此选择的分割线最少,即不选的最多,而显然不选的分割线组成二分图的一个独立集,因此问题转化为求二分图的最大独立集

时间复杂度 \(O(nm\sqrt {nm})\)

代码

例 9:[AGC037D] Sorting a Grid

给定 \(n\times m\) 的矩阵 \(A\)(值为 \(1\sim n\times m\) 的排列),行内重排得到矩阵 \(B\)\(B\) 列内重排得到矩阵 \(C\)\(C\) 行内重排得到矩阵 \(D\),其中 \(D_{i,j}=(i-1)m+j\),求一组可能的 \((B,C)\)\(n,m\le100\)

左中右三部分点,左侧 \(n\) 个点表示 \(A\)\(B\) 的行,右侧 \(n\) 个点表示 \(C\)\(D\) 的行,中间 \(n\times m\) 个点表示 \(B\)\(C\) 的值

\(A_{i,j}=x\),则左侧第 \(i\) 个点向中间第 \(x\) 个点连边

\(D_{i,j}=y\),则中间第 \(y\) 个点向右侧第 \(i\) 个点连边

源点向左侧点连边,右侧点向汇点连边

所有边的容量都是 \(1\)

进行 \(m\) 次匹配,每次确定 \(B\)\(C\) 的一列(每次匹配后删去已经匹配的边,重置源汇的边),可证每次都为完美匹配

\(x\) 次匹配中 \(i-v-j\)(其中 \(i\) 为左侧点编号,\(j\) 为中间,\(k\) 为右侧)表示 \(A\) 的第 \(i\) 行有值 \(v\)\(B\)\(i\) 行第 \(x\) 个为 \(v\)\(C\)\(j\) 行第 \(x\) 个为 \(v\)\(D\)\(j\) 行有值 \(v\)

可证其正确性

时间复杂度 \(O(m\cdot nm\sqrt{nm}=nm^2\sqrt{nm})\)

代码

例 10:CF704D Captain America

给定平面上 \(n\) 个点,要给每个点染红色或黑色,\(m\) 条限制 \((1/2,l,x)\),表示直线 \(x=l/y=l\) 上两种颜色点数量之差不超过 \(x\),求一种染色方案,使黑点数量乘以 \(b\) 加红点数量乘以 \(r\) 最小,或判定无解,\(n,m\le10^5,x,y\le10^9\)

先对坐标离散化

假定 \(r\le b\)(若 \(r>b\) 交换即可,但输出方案时要注意)

若没有限制,则全染红最优

\(xct_i\) 表示 \(x=i\) 的点的数量,对于限制 \((1,l,x)\),相当于要求直线 \(x=l\) 上红点数量在 \(\left[\max\left(0,\left\lceil\dfrac{l-xct_i}2\right\rceil\right),\min\left(xct_i,\left\lfloor\dfrac{l+xct_i}2\right\rfloor\right)\right]\) 范围内(若某一条限制对应的区间为空则直接判无解)

\((2,l,x)\) 同理

问题转化为在给定点集中选出一个子集,使得其满足 \(m\) 条形如直线 \(x=l/y=l\) 上选出的数量在 \([L,R]\)的要求

对于每个 \(x\) 坐标建立一个左部点,每个 \(y\) 坐标建立右部点,源点向左部点连边的上下界为该左部点对应 \(x\) 坐标最紧的限制,右部点向汇点的边的上下界为该右部点对应 \(y\) 坐标最紧的限制

对于每个点,在其 \(x\) 坐标对应左部点和 \(y\) 坐标对应右部点之间连上下界为 \([0,1]\) 的边

则得到的图的上下界可行流即为一组解(若没有可行流则判无解)

由于要权值最小,因此红点最多,求上下界最大流即可

时间复杂度 \(O((n+m)\sqrt{n})\)

代码

例 11:CF1592F2 Alice and Recoloring 2

给定一个 \(n\times m\)\(0/1\) 矩阵 \(s\),每次用 \(1\) 的代价翻转包含 \((1,1)\) 的子矩阵,用 \(2\) 的代价翻转包含 \((n,m)\) 的子矩阵,用 \(3\) 的代价翻转包含 \((n,1)\) 的子矩阵,用 \(4\) 的代价翻转包含 \((1,m)\) 的子矩阵,求使原矩阵全 \(0\) 的最小代价,\(n,m\le500\)

一次 \(3\) 操作可以转化为两次 \(1\) 操作,且代价更小,因此最优解一定没有 \(3\) 操作;同理也没有 \(4\) 操作

因此转化只有为翻转左上角和翻转右下角两种操作

\(a_{i,j}=s_{i,j}\oplus s_{i+1,j}\oplus s_{i,j+1}\oplus s_{i+1,j+1}\)(假定 \(s\) 给定范围外全为 \(0\)

\(1\) 操作相当于 \(a\) 单点翻转,\(2\) 操作相当于同时翻转 \(a_{i,j},a_{n,j},a_{i,m},a_{n,m}\),其中 \(1\le i<n,1\le j<m\)

可证至少存在一种最优方案,其中对 \((i,j)\) 进行 \(2\) 操作的必要条件为 \(a_{i,j},a_{n,j},a_{i,m}\) 同时为 \(1\),且所有进行 \(2\) 操作的点的横纵坐标互不相同

建立二分图,左侧 \(n-1\) 个点表示 \(x\) 坐标,右侧 \(m-1\) 个点表示 \(y\) 坐标,若 \((i,j)\) 满足上述要求,则对应两点连边

显然 \(2\) 操作越多,剩下需要 \(1\) 操作处理的点越少,因此求图的最大匹配,设为 \(k\)

\(a_{n,m}\) 异或 \(k\bmod 2\),设 \(a\)\(1\) 的数量为 \(S\),则答案为 \(S-k\)

时间复杂度 \(O((n+m)\sqrt{nm})\)

代码

例 12:CF802C Heidi and Library (hard)

一个容量为 \(k\) 的容器,每次可以花 \(c_i\) 的代价放入一个 \(i\) 类物品,或取出其中一个物体,要求第 \(i\) 时刻必须有 \(a_i\) 号物体(同一时刻可以多次操作),求最小代价,\(1\le a_i\le n\le80\)

每个元素在容器中的时间为若干区间

先假设每个元素在第一次需要时放入,最后一次需要之后移除,然后考虑每时刻容量限制对答案的增量

即先选出整个区间,然后将整个区间划分为若干子区间,以减小容量

每时刻最多可以保留 \(k\) 个元素到下一时刻,因此 \(i\)\(i+1\) 连容量 \(k\) 费用 \(0\) 的边

设上一个与 \(i\) 时刻需要的元素相同的时刻为 \(pr_i\)(若不存在则为源点),则可以将 \(a_i\) 的整个区间在 \(pr_i\)\(i\) 之间划分开,需要花 \(c_{a_i}\) 的代价重新放入,为了避免 \(i\) 时刻放入再取出而不记容量,假设是在前一时刻放入的,\(pr_i\)\(i-1\)(为了避免出现 \(0\) 时刻,若 \(i=1\) 则不需要减 \(1\),因为此时一定是源点向其连边)连容量 \(1\) 费用 \(c_{a_i}\) 的边

对于每种元素 \(i\),设其最后出现时间为 \(t_i\)(若没出现则忽略),则要将 \(i\) 各个区间的贡献计入答案,\(t_i\) 向汇点连容量 \(1\) 费用 \(0\) 的边

总点数 \(n+2\),总边数 \(O(n)\)

时间复杂度 \(O(nmf)\)

代码

参考

输出方案:CF132E Bits of merry old England \(\quad\) 代码

例 13:P2045 方格取数加强版

\(n\times n\) 的矩阵 \(a\),选择 \(k\)\((1,1)\)\((n,n)\) 的路径,最大化路径经过的点的总权值(经过多次只算一次权值),\(n\le 50,k\le 10,0\le a_{i,j}\le1000\)

相当于一张网格图上选择不超过 \(k\) 条路径,最大化路径覆盖到的点的总权值和

\(n\times n\) 个格子分别建立入点和出点,格子 \((i,j)\) 对应的入点向出点连两条边,一条容量 \(1\) 费用 \(a_{i,j}\),表示可以选择 \(1\) 次,一条容量 \(k-1\) 费用 \(0\),表示剩下至多 \(k-1\) 次经过都没有收益

每个格子的出点向其下方和右侧相邻格子的入点连容量 \(k\) 费用 \(0\) 的边

源点为格子 \((1,1)\) 的入度,汇点为格子 \((n,n)\) 的出点

跑最大费用最大流即可,时间复杂度 \(O(NMF)=O(n^2\times n^2\times k)=O(n^4k)\)

代码

题单

\(\text{vjudge}\)Bipartite Graph & Flow

\(\text{luogu}\)
24.12.9 BpGr&Fl \(\quad\) 网络流与线性规划 24 题

参考

  1. \(\text{2024.12.19 Flow.pdf \; \;by lanos212}\)
posted @ 2025-03-31 10:35  Hstry  阅读(71)  评论(0)    收藏  举报