网络流练习
网络流练习#
若是一个点经过的次数有限制,则需要拆点
拆点的妙用博大精深
注:下文中 指超级源点, 指超级汇点
最大流#
P1231 教辅的组成#
题意:
现在有 三种东西,分别有 个
告诉你 组 的对应关系, 组 的对应关系
只有 同时对应 和 , 才能和 与 配成一套
问在不重复的条件下最多可以配成几套
思路:
很基础的最大流
由于 对应 和 ,考虑建图时把所有 放中间 放两边
从 向所有 连一条容量为 的边,从所有 向 连一条容量为 的边
从所有 向所有 连一条容量为 的边,从所有 向所有 连一条容量为 的边
跑最大流就行
但是我 了
这是因为 在中间,若是像下面一样会算两次:
so,我们把中间的所有 拆成两个点,加一条容量为 的边
最大流即为答案
P2472 蜥蜴#
题意:
在一个 行 列的网格地图中有一些高度不同的石柱,第 行 列的石柱高度为 。
一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外。
每行每列中相邻石柱的距离为 ,蜥蜴的跳跃距离是 ,即蜥蜴可以跳到平面距离不超过 的任何一个石柱上。
石柱都不稳定,每次当蜥蜴跳跃时,所离开的石柱高度减 (如果仍然落在地图内部,则到达的石柱高度不变)。
如果该石柱原来高度为 ,则蜥蜴离开后消失,以后其他蜥蜴不能落脚。
任何时刻不能有两只蜥蜴在同一个石柱上。
思路:
数据范围很小,考虑网络流
因为每个石柱都有经过次数限制,所以要位置 拆成点 和 ,且 和 之间连一条容量为 的边
用 表示跳到了石柱 , 表示从 点开始跳向别的石柱
若是能从一个石柱 跳到另一个石柱 ,那么就从 向 连一条容量为 的边
若是能从一个石柱 跳出边界,那么就从 向 连一条容量为 的边
我们可以假设最开始每只蜥蜴都不在石柱上,而是在源点
然后从 向每个蜥蜴初始位置 连一条容量为 的边,表示一只蜥蜴
这样就可以巧妙地解决这个问题
最大流 表示的是最多有多少只蜥蜴能跳走
记录蜥蜴总数 ,跑一遍网络流,最终结果为
P2766 最长不下降子序列问题#
题意:
给你一个正整数序列 ,求:
- 最长不下降子序列的长度
- 计算从给定的序列中最多可取出多少个长度为 的不下降子序列。(每个元素只允许使用一次)
- 计算从给定的序列中最多可取出多少个长度为 的不下降子序列。( 只允许使用一次, 可以使用无数次)
思路:
第一问是经典问题,我们可以得到递推式:
第二问考虑网络流
首先每个元素被限制了只能使用一次,因此拆点,把 拆成 和
若 则从 向 连一条容量为 的边,表示 可以作为不下降子序列的起点
若 则从 向 连一条容量为 的边,表示 可以作为不下降子序列的终点
若 且 ,则从 向 连一条容量为 的边,表示可以拼出长度 的不下降子序列
显然,这样建图后跑一边最大流即可
对于第三问,我们只需要在第二问的基础上把 ,,, 的容量均改成 即可
最小割#
P4313 文理分科#
题意:
有 个人,每个人要么选文科,要么选理科
第 行 列的人选文科可以获得快乐值 ,选理科可以获得快乐值
若是一个人选的文科且上下左右的人都是文科,他可以获得额外快乐值
若是一个人选的理科且上下左右的人都是理科,他可以获得额外快乐值
求这些人的快乐值总和最大是多少
思路:
非 即 ,典型的最小割
先不考虑额外快乐值
在集合 中表示选文科,在集合 中表示选理科
从 向点 连容量为 的边,从点 向 连容量为 的边
这样求最小割,割掉最少不要的快乐值,剩下的就是答案
考虑额外快乐值
我们新建一个节点 对应点 的文科额外快乐值,从 向点 连容量为 的边
考虑上下左右及自己都必须选文科,因此从 向 ,,,, 都连一条容量为 的边
显然这五条边是不会被割掉的
因此若是这五个点中有两个点不在一个集合内,就必须要断掉它们之间的联系,因为 把它们连在一起了
此时不能割容量为 的边,就只能割容量为 的边
理科的同理,我们新建一个节点 对应点 的理科额外快乐值,从 向点 连容量为 的边
从 ,,,, 向 都连一条容量为 的边
根据最小割=最大流
跑一边 得到最大流 ,最终的答案是
P2762 太空飞行计划问题#
题意:
给定一张图,有左侧的点和右侧的点,左侧的点点权为正(对应试验),右侧的点点权为负(对应器材),如果选择了左侧的某个点就必须要选右边的一部分点。要求最大化点权和。
思路:
若是左侧的点需要右侧的点,则连一条从左侧的点向右侧的点的有向边,这样问题就转换为:
给定一个有向无环图,点有点权,选择一个子图,满足子图上如果选择了一个点就必须选择它后继的所有点。最大化点权和。
这是一个经典最小割问题,叫做最大权闭合子图问题
建图操作如下:
从 向所有正权值的点连一条权值为点权的边,从所有负权值的店向 连一条权值为点权绝对值的边
保留原图中所有的边且容量为正无穷
则原图中最大点权和为原图中正点权权值和减最小割
包含所有要的点, 包含所有不要的点
最小割割去的边必然与 或 相邻,因为其他的边容量均为
当我们选择要一个正权值点的时候,必然会将其放入集合 ,这样就会割掉与其相连的负权值点与 的连边,这时候割去了需要减去的值
当我们选择不要一个正权值点的时候,必然会将其放入集合 ,这样就会割掉其与 相连的边,这时候割去了需要减去的值
这样求得的割就是原图正点权和需要减去的部分,最小割就能减的最少,这样点权和最大
P3227 切糕#
题意:
你在切一个蛋糕,蛋糕每个点有一个非负不和谐值 ,切蛋糕的规则如下:
首先将每一个竖列的坐标用 表示,数列上的点就是
每次在每一数列选择一个点
对于数列 我们选的点高度记作 ,那选的点坐标即为
定义:竖列 的相邻竖列坐标可表示为
选点坐标时有一个限制:每一个竖列选的坐标 与其相邻的竖列 坐标高度差不超过
即
现在求
思路:
先去掉高度差不超过 的条件,那么这就变成了一个求最小割的题目
我们直接把每一个竖列的所有点依次相连,容量为 ,且从 连一条到这列起点,容量为 的边,从这列终点连一条到 ,容量为 的边
但是还有高度差不超过 的条件,所以考虑让建好的网络中即使割掉高度差超过 的地方也无影响
于是我们就只需要从 向 和 连一条容量为 的边
会发现这样的话即使割掉所有不合法的边仍能从 走到
画图模拟一下就可以理解了
最后的结果就是最小割
P2805 植物大战僵尸#
题意:
给定一个有向图,点有点权,选择一个子图,满足子图上如果选择了一个点就必须选择它之前的所有点。最大化点权和。
这里的之前所有点指从这个点出发,沿着反向边能跑到的所有点
思路:
这个题无非就是这个的变式,是一个最大权闭合子图问题
但是这道题需要除去环,所以用拓扑排序
若是拓扑排序的队列为空但某个点入度仍大于 ,则此点在一个环内,应该除去
而且这道题边是反的,因此跑完拓扑排序后把边反过来,跑一边网络流就行
具体做法不再叙述
费用流#
P1251 餐巾计划问题#
题意:
一个餐厅在相继的 天里,每天需用的餐巾数不尽相同。
假设第 天需要 块餐巾( )。餐厅可以购买新的餐巾,每块餐巾的费用为 分;或者把旧餐巾送到快洗部,洗一块需 天,其费用为 分,或者送到慢洗部,洗一块需 天(),其费用为 分()。
每天结束时,餐厅必须决定将多少块脏的餐巾送到快洗部,多少块餐巾送到慢洗部,以及多少块保存起来延期送洗。但是每天洗好的餐巾和购买的新餐巾数之和,要满足当天的需求量。
试设计一个算法为餐厅合理地安排好 天中餐巾使用计划,使总的花费最小。
思路:
每一天要处理两件事:准备干净餐巾以及处理脏餐巾
因此考虑把每个点拆成两个:早上和晚上,早上准备干净餐巾,晚上处理脏餐巾
建立一个源点 和一个汇点
- 从 向第 天早上连一条容量为 ,费用为 的边,表示每一天可以购买任意多餐巾
- 从第 天早上向汇点连一条容量为 ,费用为 的边,表示第 天早上需要准备 的餐巾
- 从源点向第 天晚上连一条容量为 ,费用为 的边,表示第 天需要处理的脏餐巾数量
- 从第 天晚上向第 天晚上连一条容量为 ,费用为 的边,表示第 天的脏餐巾留到第 天
- 从第 天晚上向第 天早上连一条容量为 ,费用为 的边,表示快洗第 天的脏餐巾
- 从第 天晚上向第 天早上连一条容量为 ,费用为 的边,表示慢洗第 天的脏餐巾
这样就做完了
P2153 晨跑#
题意:
有 个点, 条边,起点为 ,终点为 ,每个边都有边权
求 最长有几条的路线(满足每次经过的点都不相同),且在这个情况下最少需要跑的路程是多少
思路:
这不是最小费用最大流吗?
把原路线容量设为 ,费用设为边权就可以求解
但是要满足每次经过的点都不相同
考虑拆点
把点 拆成 和 ,从 向 连一条容量为 费用为 的边
这样就行了
答案分别是最大流和最小费用
P2469 星际竞速#
题意:
给一张 DAG,边有边权
你最开始不在图内
你可以耗费 的代价直接到达 点,也可以消耗 的代价从 走到
求使所有点都被走到的最小代价
思路:
我们可以换一种理解方式:
每次都不在图内,然后瞬移到某一点 ,然后再走
考虑费用流,让你在最大流的时候把每个点都遍历一遍,然后同时求出最小代价
从 点开始表示出发,走到 点表示结束
因此我们可以把所有边容量设为 ,这样无论如何最大流的结果都不会变
若是你想在 点结束,你必定是位移到 或从某处走到
考虑拆点
我们把 点 拆成 和 ,然后从 向 连费用为 的边, 向 连费用为 的边, 向 连费用为 的边
若存在边 ,则从 向 连费用为 的边
这样的话对于每一个点 对应的 都会走向 ,并且必定会由 或前面的点走到,可以更新最小答案
所以这种做法正确,最小费用即为答案
P4843 清理雪道#
题意:
从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向。
你们拥有一架直升飞机,每次飞行可以从总部带一个人降落到滑雪场的某个地点,然后再飞回总部。从降落的地点出发,这个人可以顺着斜坡向下滑行,并清理他所经过的雪道。
由于每次飞行的耗费是固定的,你想知道如何用最少的飞行次数才能完成清理雪道的任务。
思路:
我们把图中的每一条边 拆成两条边:一条流量为 ,费用为 ;一条流量为 ,费用为 。
然后源点向每个入度为 的点(也就是链覆盖的起点)连边,流量为 ,费用为
每个出度为 的点(也就是链覆盖的终点)向汇点连边,流量为 ,费用为
然后跑最大费用最大流,增广的次数即为答案
因为每次增广都相当于覆盖一条链
若原图中的边 没有走过,增广过程中,程序肯定会优先选择费用为 的边,表示清理它
否则这条边已经清理过了,就只路过不清理
最大费用最大流能够保证用最优的方式覆盖所有边
因此当所有费用为 的边都被经过之后,整个图也就覆盖完了,答案就是覆盖的次数
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现