网络流 24 题
前言
貌似并不知道要说什么(?)
网络流写麻了
(一)P3358 最长 $k$ 重区间集问题
题意:给定 $n$ 个左闭右开的区间,从这些区间中选取一些区间,使得数轴上没有任何一个点被超过 $k$ 个区间包含,并使得区间覆盖长度最大。
题意没给 $l,r$ 范围,先离散化。
先找流量和费用。首先有一个【每个区间只能选择一次】的隐性条件限制。可以想到将次数作为流量,显然长度就作为花费。
那么怎么表示选择一个区间呢?我们可以将区间左端点连向右端点,流量为 $1$,费用该区间的长度。
一点最多选 $k$ 次,那么我们对于数轴上每一个点 $i$ 连向 $i+1$,容量为 $k$,费用为 $0$。
跑一边最大费用最大流即可。
(二)P4014 分配问题
题意:$n$ 个工件分给 $n$ 个工人,第 $i$ 个人做第 $j$ 个工件的效益为 $c_{i,j}$,求问在一个零件只能匹配一个工人,并且一个工人只能加工一个零件的情况下,效益最大是多少。
显然有一个二分图的模型,把工人放到左边,零件放到右边。中间是若干边。
很套路的,建立一个虚拟源点 $s$,连向每一个工人,容量为 $1$,费用为 $0$,表示一个工人只能匹配一个,没有匹配零件所以没有费用。
同样,建立一个虚拟汇点 $t$,每一个零件连向汇点,容量为 $1$,费用为 $0$。
之后对于第 $i$ 个工人和第 $j$ 个零件连一条容量为 $1$,费用为 $c_{i,j}$ 的边,表示一个工人和一个零件只能匹配一次,获得的价值为 $c_{i,j}$。
要使效益最大,最后跑一边最大费用最大流。
(三)P2774 方格取数问题
题意:$m\times n$ 的方格,每个方格有一个数,选取若干的数,使得任意两个选取的数在方格中没有公共边,求最大和。
直接做不好做,考虑假设我们选取的了所有的数,那么现在我们要求最少删掉的代价。
这样就很像最小割了。
我们对于图黑白染色,若 $(i+j)\bmod 2=1$,则该点为黑,否则为白。
建立虚拟源点 $s$,和虚拟汇点 $t$。我们令 $s$ 连向每一个黑点,容量为点权。每一个白点连向 $t$,容量同样为点权。表示我们删去这个点需要的价值。
我们将每个黑点连向与它四联通的白点,容量为无限大。
根据最大流 = 最小割,跑一遍最大流就行了。
为什么这样做是对的,性感理解一下。但考虑一张 $s\to u\to u'\to t$ 的图,我们跑最大流肯定是在 $s\to u$ 和 $u'\to t$ 这两条边之间取的最小值,因为如果取了最大值就会超过另一条边的容量。这也就是求得删去的数的最小值。边权为 $\infty$ 表示这两个点见只能选择一个,因为最小割肯定不会割掉边权为 $\infty$ 的边。
最后有所有点的总和减去最小割即可。
(四)P4015 运输问题
题意:单位 $i$ 有 $a_i$ 单位的货物,商店 $j$ 有 $b_j$ 的货物需求量,保证 $\sum a_i=\sum b_j$。第 $i$ 个单位运到第 $j$ 个商店需要花费 $c_{i,j}$ 的代价,求最小和最大费用。
看出这是一个二分图模型,把单位放到左边,商店放到右边。
很显然是个费用流。货物量就是流量,代价就是费用。因为题目中保证 $\sum a_i=\sum b_j$,所以想到源点流出的流量等于汇点接受的流量。
建立虚拟源点 $s$ 和虚拟汇点 $t$,$s$ 连向每一个单位,容量为该单位的货物量,费用为 $0$。每一个商店连向 $t$,流量为该商店的需求量,费用为 $0$。
最后对于每一个单位连向每一个商店,容量无限大,费用就是那个代价。
最后跑一次最小费用最大流和一次最大费用最大流即可。
(五)P2762 太空飞行计划问题
题意:有 $m$ 个实验。每个实验只能进行一次,但会获得相应的奖金,有 $n$ 个仪器,每个实验都需要一定的仪器,每个仪器可以应用于多个实验,但需要一定的价值,问奖金与代价的差的最大值是多少?输出方案。
我们假设选择了所有实验,但所有的仪器先不选,然后找到一个花费最小的方案去掉若干个实验。
这就像最小割了。跟方格取数问题一样。
我们建立虚拟源点 $s$ 和虚拟汇点 $t$,然后 $s$ 连向每一个实验,流量为奖金,每一个零件连向 $t$,容量为花费。
求最小割,就相当于跑最大流。
怎么解释这件事情。考虑我们一开始求得奖金总和,假设我们割掉了某一个仪器,那么就相当于这个仪器不选,恰好减去他的奖金。如果割掉了某个零件,就相当于选了这个零件,同样花费了它的代价。
至于输出方案,有一个结论,在最后一次 $\text{Dinic}$ 中,被分到层上点都不会被割掉。
性感证明一下:我们在选择从 $s$ 到仪器的边中,最后一次肯定会选择满流的点,而那些没有满流的点都是被割掉的。然后会对那些满流的节点分层,最后只需判断一下一个点是否分了层即可。
(六)P2770 航空路线问题
题意:从西到东有 $n$ 个城市,$m$ 个航线,每个航线单向连接两个城市。求从最西的城市到最东的城市再回最西城市,除最西和最东城市每个城市只经过一次情况下,经过城市数最多,并输出方案。
首先可以得出一些性质:考虑来回一趟的旅程就相当于从起点到终点两趟,两次不经过相同的城市。【每一个城市只能遍历一次】的条件说明每一条航线也只能遍历一次。
【每一个城市只能经过一次】这一限制条件很套路,将每一个城市拆成两个点,一个入点 $u$ 和一个出点 $u'$,我们连从 $u$ 到 $u'$ 容量为 $1$ 的边,表示这个点只能经过一次,而题目又要使得经过城市数尽量多,所以可以看出是最大费用最大流的问题,我们让 $u$ 到 $u'$ 的费用为 $1$,表示经过了一个城市。
之后对于每一条航线,根据一开始推出的每条航线只能经过一次,我们对于每一条航线 $(x,y)$,从 $x'$ 到 $y$ 连一条容量为 $1$,费用为 $0$ 的边。
最后跑最大费用最大流即可。
输出方案仍然很简单,网络流有一个性质就是,流量为 $0$ 的边一定是被选上的。那么我们从起点开始 $dfs$,每一次找边权为 $0$ 的边暴搜下去。然后搜两次,第二次反着输出,因为是返程。
(七)P2754 星际转移问题
题意:有 $n$ 个太空站,容量无限,$m$ 艘飞船,每艘船有容量 $h_i$,第 $i$ 搜飞船会周期性的停靠太空站,$k$ 个人在地球 $0$,要使所有人都飞往月球,最快需要多少时间。
考虑按时间分层的 $\texttt{trick}$。
我们枚举答案 $T$,那么我们对于每一个船在 $T-1$ 时刻所到达的星球与 $T$ 时刻所到达的星球连一条容量为 $h_i$,表示最多装 $h_i$ 的人。
当然,上一个时刻的每一个空间的人都可以停留,那么我们将每一个星球上一个时刻和这一个时刻连一条容量为 $\infty$ 的边,表示这个空间站的容量是无限大的。
特殊的,我们建立虚拟源点 $s$ 和虚拟汇点 $t$,我们将 $s$ 连向地球,容量无限大,月球连向 $t$,容量也为无限大。
对于每一个时刻都跑最大流,直到最大流不小于 $k$ 为止,说明可以载够 $k$ 个人了。
判断无解考虑并查集即可。
(八)P3254 圆桌问题
题意:$m$ 个单位,第 $i$ 个单位派出了 $r_i$ 个代表。有 $n$ 个桌子,第 $i$ 个桌子可以容纳 $c_i$ 人,要求同一个单位的代表不能做相同桌子,求一个合法方案。
不难看出这也是一个二分图模型,把单位放在左边,桌子放在右边。
我们先建立虚拟源点 $s$,让 $s$ 连接每一个单位,容量为改单位的代表人数,表示一个单位的初始人数,我们想让这些人都不在同一个餐桌,那么就可以通过流量来起限制作用,我们将每一个单位向每一个餐桌连接一条流量为 $1$ 的边,表示该单位只能对该桌派出一个代表。而餐桌也是有名额限制的,我们将每一个餐桌向虚拟汇点 $t$ 连一条容量为 $c_i$ 的边。
如何判断无解,充要条件是源点的流出量必须等于汇点的接收量。
那么如何判断每一个人都坐在哪些位置呢?还是判断每一条边的流量是否为 $0$,即可找到每一个人坐到了哪一个餐桌。
(九)P1251 餐巾计划问题
题意:有 $n$ 天,每一天会需要 $r_i$ 个毛巾。可以直接购买新毛巾,或将现有毛巾送到慢洗部或快洗部花一定的钱洗若干天。毛巾用一天就会脏。求最小花费。
我们发现并没有很显然的二分图模型,但发现有【毛巾用一天就会脏】这一条件,提示我们按照【白天】和【黑夜】分层。
我们对于每一天构建两个点,一个黑天一个白天。我们将黑天放左边,白天放右边。
我们知道,每一天的 $r_i$ 个毛巾是必须要满足要求的,那么我们可以把毛巾需求量作为流量。而题目又要使花费最小,不难发现是一道最小费用最大流的问题。
我们建立虚拟源点 $s$,我们将 $s$ 向每一个黑天连容量为 $r_i$,费用为 $0$ 的边。表示获取这么多的脏毛巾。
同样,我们建立虚拟汇点 $t$,我们将每一个白天向 $t$ 连容量为 $r_i$,费用为 $0$ 的边,表示当天用了这些干净的毛巾。
现在考虑怎样将从源点获取的脏毛巾转变为干净的毛巾。
最直接的是买毛巾。直接从源点获取。向白天连一条容量无限大,费用为每块餐巾的费用。
之后就是快洗和慢洗的问题了,将当天晚上连向洗完那天的白天,容量为无限大,费用为快洗或慢洗的花费。
还有一个小坑,就是当天的脏毛巾可以拖到明天,或是更远几天再洗,那么我们将每一天晚上连向第二天晚上一个容量为无限大费用为 $0$ 的边。
跑一遍最小费用最大流即可。
(十)P2763 试题库问题
题意:有 $n$ 个试题,每个题有若干个 $\texttt{tag}$,要抽取 $m$ 个道题组成的试卷,类型 $i$ 的试题需要 $a_i$ 个。求一个合法的试卷组合。
这也有一个二分图模型,左边是试题,右边是类型。
由于一个试题只能用一次,那么我们从源点向每一个试题连一个容量为 $1$ 的边。
而当我们选择一个试题之后,就会获得一些 $\texttt{tag}$,那么我们将每一个试题向它的每一个类型连一条容量为 $1$ 的边,最后每一个类型向汇点 $t$ 连容量为 $a_i$ 的边。表示 $i$ 类型的题需要 $a_i$。
最后跑一遍最大流。
输出的方法还是一样,找流量为 $0$ 的边就行了。
(十一)P2766 最长不下降子序列问题
题意:给定长度为 $n$ 的数列,求:①最长不下降子序列的长度 $s$;②每一个元素只能使用一次的情况下,最多可以取出多少个长度为 $s$ 的不下降子序列;③若 $a_1$ 和 $a_n$ 可以使用多次,最多可以取出多少个长度为 $s$ 的不下降子序列。
第一问直接 dp,并记录最长不下降子序列的长度 $F$ 和 $dp_i$,表示以 $i$ 为结尾的最长不下降子序列的长度。
考虑二三问。
首先发现每个元素只能使用一次,那么套路的,我们对于每一个元素拆点,中间的流量为 $1$,表示只用一次。
然后枚举 $dp$ 值为 $1$ 的位置,这种位置只能放在开头,那么我们将 $s$ 向它连一条容量为 $1$ 的边。
同理,再枚举 $dp$ 值为 $F$ 的点,这种点只能放在结尾,所以我们将它连向 $t$,容量为 $1$。
然后考虑把 $s$ 和 $t$ 关联起来,很容易想到,$dp$ 值其实就相当于一个分层操作,对于两个点 $i,j$,如果 $a_i\ge a_j$ 且 $dp_i=dp_j+1$,那么说明 $j$ 可以转移到 $i$,我们将 $j$ 到 $i$ 连一条容量为 $1$ 的边。
跑一遍最大流就是第二问的答案。
第三问也很简单,我们将 $s$ 到 $1$ 和 $1$ 到它的拆出来的点的流量都改成无穷大。
但是只有在 $dp_n=F$ 的情况下我们才更改 $n$ 到 $n$ 对应的拆出来的点,和拆出来的点到 $t$ 的流量。这是一个小坑。
最大流即可。
(十二)P3355 骑士共存问题
题意:在 $n\times n$ 的棋盘上放置马,使得任意两个马不攻击,有 $m$ 个给定的位置不能放,求最多放几个马。
虽然不能说跟刚刚的方格取数问题一模一样,但也是很类似了。
同样假设取了所有点,然后最小化减少矛盾的马的数量就是最大化答案。
这样对原图黑白染色,然后跑最小割即可。
(十三)P4013 数字梯形问题
题意:给定一个数字梯形,从最顶端开始走 $m$ 条路径,每次朝左下或右下走,三问(一)路径不能相交(二)只能在节点处相交(三)可以在节点或边相交。
我们发现起点有 $m$ 个,是分散的,不如先建立 $s$ 连向第一行的每个数。然后最后一行的每一个点连向 $t$。容量 $1$,费用 $0$。
先考虑第一问,发现又有节点只能经过一次的限制。直接拆点,中间连容量为 $1$,费用为该节点的权的边。
然后每一个点的出点连向下面一行左边和右边的点,容量为 $1$,费用为 $0$。因为边也只能经过一次。
对于第二问,我们直接将每个点的入点和出点的容量改为 $\infty$,表示每个点可以经过无限次。有一个小坑就是最下面一行的每一个点连向 $t$ 的容量也都改为 $\infty$,因为某一条路径到达最下面的某一个点后,已经结束了,所以跟到终点的容量没有关系。
对于第三问,除了 $s$ 到第一行每一个点的边以外的所有边的容量都改为 $\infty$。
然后你就会发现一个特别恶心的事情,对于每一问都得重新建图。
(十四)P2764 最小路径覆盖问题
题意:给定一个 $\texttt{DAG}$,最少多少条简单路径能覆盖所有点。输出路径。
关于这道题有一个非常巧妙的解法。
首先发现答案的上限是 $n$,因为每一个点都可以被它直连的一条边覆盖,一共 $n$ 个点,所以答案最多是 $n$。
然后考虑合并边,每合并两条边答案就减少 $1$,所以考虑通过最大流来找出边的最大合并数。
这样就很好做了,对于每一个点拆点,然后 $s$ 连向每一个入点,容量 $1$,每一个出点连向 $t$,容量 $1$,之后对于每一条 $(x,y)$,连 $x$ 到 $y'$ 的一条容量为 $1$ 的边即可。表示合并了两个点。
最后跑一边最大流,答案就是 $n$ 减去最大流。
输出方案采用并查集维护起点,然后对于每一个起点顺着残余网络暴力 $dfs$ 即可。
(十五)P4009 汽车加油行驶问题
题意:给定 $n\times n$ 的方格,坐上 $(1,1)$ 为起点,右下 $(N,N)$ 为终点,$X$ 轴向右为正,$Y$ 轴向下为正,在若干个点上设置了油库可供加油,汽车只能沿着网格边走,遇到加油站必须加油,装满油后最多走 $k$ 条边,初始油量已满。汽车移动时若 $X$ 或 $Y$ 坐标减小,则需花费 $B$ 的费用。加油需要花 $A$ 的费用,可以在某一个没有加油站的点花 $C$ 的费用使油量变满。求最小费用。
这道题很显然是分层图最短路,所以考虑网络瘤。
显然费用流。
我们将图分为 $k+1$ 层,第 $0$ 层表示满油,第 $i$ 层表示用掉了 $i$ 个单位的油。第 $k$ 层就表示油被用光。
我们用三元组 $(x,y,z)$ 表示一个点 $(x,y)$ 的已用油量 $z$。
建立虚拟源点 $s$ 和虚拟汇点 $t$。
首先从 $s$ 到 $(1,1,0)$ 连一条流量 $1$,费用为 $0$ 的边,表示初始油量已满。对于每一个 $i$ 连从 $(n,n,i)$ 到 $t$ 的流量为 $1$,费用为 $0$ 的边,表示到达终点后车的可能的 $k+1$ 种状态。
之后考虑有加油站的点 $(i,j)$,汽车会被强制消费。所以 $(i,j,z)$ 连向 $(i,j,z+1)$ 流量 $1$,费用 $A$ 的边。然后枚举周围点,从状态 $0$ 到状态 $1$ 连边。注意如果横纵坐标减小应该额外花费 $b$。
然后对于普通点也是同理,只不过连周围点的时候要枚举当前点的状态。
特殊的,若当前点的状态是 $k$ 即油没了,连一条 $(i,j,k)$ 向 $(i,j,0)$ 流量 $1$ 费用 $a+c$ 的边。
(十六)深海机器人问题
题意:有一个 $P\times Q$ 的网格图,左下角为 $(0,0)$,右上角为 $(Q,P)$。有 $k$ 个机器人在不同出发地点,有若干目标地点,每个目标地点只能容纳 $r_i$ 个机器人,有些地方有生物标本,每个生物标本有价值,每个生物标本只能被第一个到达它的机器人取走,机器人只能向北或东走,若干机器人可以占据同一位置。求最高价值。
很显然的最大费用最大流了。每个点分别向右边的点连两条边,一条容量 $1$,费用为该点价值,一条容量无限,费用 $0$,表示取走一次再不能取。向上同理。
最后把起点和 $s$ 连起来,终点和 $t$ 连起来,容量为机器人数目,费用为 $0$。
最后跑最大费用最大流即可。
(十七)最长 $k$ 重线段集问题
题意:给定平面直角坐标系 $n$ 个线段,从这些区间中选取一些线段,使得对于任意一点 $p$ 没有任何一条直线 $x=p$ 与超过 $k$ 个线段,并使得线段长度最大值。
其实是最长 $k$ 重区间集问题的升级版,把区间放到直角坐标系上了。
那么一个很直接的想法就产生了,直接把线段投影到 $x$ 轴上!这样就和最长 $k$ 重区间集问题一模一样了。
但是很遗憾,这个想法是错误的,反例也很简单,假设说两条线段在一条是平行于 $y$ 轴的,投影之后就变成一个点了,导致错误。
那么不难想到把线段的长度都扩大一倍,即将线段 $i$ 的左右端点 $x_i,y_i$ 都扩大一倍变成 $(2x_i,2y_i)$。
而对于一个左右端点相同的区间,可以将它更改成 $(2x_i,2x_i+1)$。其它节点也都需要更改成 $(2x_i+1,2y_i)$ 的形式。
(十八)魔术球问题
题意:$n$ 个柱子,依次放入无限个球,球从 $1$ 开始编号。每次只能在某根柱子最上面放球,并且在同一个柱子中,任何两个相邻球的编号之和为完全平方数。输出方案。
我们考虑当前放置的球 $i$,它有两种可能,一是放到某一根已经有魔术球的柱子上,二是自己放到一个新的桌子上。
我们将球分裂,一个入点,一个出点。
首先我们可以将 $s$ 连向入点,容量为 $1$,表示放到一个新的柱子上。出点连向 $t$,容量也为 $1$,这里很重要,表示我们成功放上了一个球。
然后枚举可以与它构成完全平方数的数 $x$,将 $x$ 的入点连向它的出点,容量为 $1$,表示一个匹配关系。
跑最大流,直到最大流大于 $n$,说明所需的柱子量超过了 $n$,那么停止。
输出方案找流量为 $0$ 的边,暴力 $\texttt{dfs}$ 即可。
还有亿点细节。
(十九)火星探险问题
题意:给定一张网格图,每个点有三种状态,平坦,障碍或岩石标本。有 $n$ 个探测车在移动中须采集岩石标本。每一块岩石标本由最先遇到它的探测车完成采集。每块岩石标本只能被采集一次。岩石标本被采集后,其他探测车可以从原来岩石标本所在处通过。探测车不能通过有障碍的地面。探测车只能从登陆处沿着向南或向东的方向朝传送器移动,而且多个探测车可以在同一时间占据同一位置。如果某个探测车在到达传送器以前不能继续前进,则该车所采集的岩石标本将全部损失。求最多获得的岩石标本数。要求打印移动方向。
一道非常板的网络流了。显然车的数量为流量,石头数为费用。
令 $s$ 向 $(1,1)$ 连流量 $n$ 费用 $0$ 的边,表示初始有 $n$ 辆车。$(n,n)$ 连向 $t$,容量 $\infty$,花费 $0$,表示结束任务。
既然涉及到每个石头只能取一次,那么显然是可以拆点的,拆为 $a_{i,j}$ 和 $b_{i,j}$。
如果 $(i,j)$ 处有石头,那么可以连 $(a_{i,j})$ 到 $b_{i,j}$ 的流量 $1$,费用 $1$ 的边,表示只能有一个车取一个石头。石头也可以被取走,连另连一条流量 $\infty$ 费用 $0$ 的边。
另外还有相邻的点连线,每次都是出点连入点,流量 $\infty$ 然后费用 $0$。
最后就是最大费用最大流。
输出路径还是暴力 $\text{dfs}$。
$$\texttt{The End.by UF}$$