网络流练习

做一些典题。主要是建模。

费用流的时间复杂度按 \(O(nmf)\) 算,最大流正常算。

P4016 负载平衡问题

可以经典贪心。设 \(K_i\) 表示第 \(i\) 个点向左边传递的货物量,\(x_i\) 表示第 \(i\) 个点本来有的货物量。最后一定满足 \(\overline x=x_i-K_i+K_{i+1}\)\(K_i<0\) 时表示从左边获得 \(-K_i\) 的货物量。

答案为 \(\sum\limits_{i=1}^n |K_i|\)

对上式变形,\(K_{i+1}=K_i+\overline x-x_i=K_1+i\cdot \overline x-\sum\limits_{j=1}^i x_j\)。设 \(g_{i+1}=i\cdot \overline x-\sum\limits_{j=1}^i x_j\),只需确定 \(K_1\) 最小化 \(\sum\limits_{i=1}^n|K_1+g_i|\)。取 \(\{-g_i\}\) 的中位数即可。

\(O(n\log n)\),瓶颈在于排序。或者快速选择 nth_element 可以做到 \(O(n)\)

费用流做法。

首先描述原本有的库存量,从原点向每个点连容量为原库存量,费用为 \(0\) 的边。再描述相邻两个之间运输货物,相邻两个之间连容量为 \(\infty\),费用为 \(1\) 的边。最后要每个位置货物量相同,用最大流限制这个,于是每个点向汇点连容量为 \(\dfrac{S}{n}\),费用为 \(0\) 的边。最后跑最小费用最大流即可。

或者稍加优化,对多于平均数的点从源点连容量为多余量,费用为 \(0\) 的边,对少于平均数的点连向汇点,容量为所需量,费用为 \(0\)。相邻的还是正常连边。这样边数会少一点,常数优化。

时间复杂度 \(O(n^3)\)

P2756 飞行员配对方案问题

就是二分图最大匹配。用最大流来做。

一个左部点只能和最多一个右部点匹配,所以从源点向每个左部点连容量为 \(1\) 的边。右部点同理,向汇点连容量为 \(1\) 的边。

左部点与右部点之间的边没有限制,容量可以是 \(\infty\),又因为一条边上流最大为 \(1\),容量也可以是 \(1\)

输出方案可以在残量网络上找到连接左部点和右部点的正向边,如果其反向边有流量,说明两个端点匹配了。

\(O(n\sqrt m)\)

P4015 运输问题

建立费用流模型。供需平衡用最大流限制,已有的货物从源点连边,所需的货物向汇点连边,容量为对应的值,费用为 \(0\)

从仓库运到商店,对应连边,容量为 \(\infty\),费用为对应值。

直接跑费用流,\(O(\text{能过})\)(数据范围不全)。

P3254 圆桌问题

题意翻译成人话就是一个桌子上至多有一个人是第 \(i\) 个单位的。用流量限制人数。将单位和桌子看成点,源点向单位连边,容量为其人数,桌子向汇点连边,容量为其可容纳人数。单位和桌子之间两两连边,容量为 \(1\)

如果存在可行方案,则必定有最大流等于总人数。

构造方案就在残量网络上检查单位和桌子之间的边的流量即可。

\(O(n^2m)\)\(n,m\) 为点数/边数。

P3355 骑士共存问题

显然黑白染色转二分图最大独立集。然后二分图上 \(\text{最大独立集}=\text{点数}-\text{最大匹配}\)。就做完了。

P2774 方格取数问题

选了一个之后限制一些不能选,转最小割。一个位置先拆点,入点和出点之间连容量为其价值的边。再黑白染色,源点向黑点的入点连容量为 \(\infty\) 的边,白点向汇点连容量为 \(\infty\) 的边。这样保证源点和汇点连出去的边不会割,会被割的只有一个位置拆出来的两个点之间的边。此处割一条边即选一个位置。

对于一个限制,从黑点的出点向四周的白点的入点连容量为 \(\infty\) 的边,保证其不会被割,由于最小割,所以若黑点被割,那么四周的白点必然不会被割。白点类似。这样就求出了最小的价值。补集即最大价值,可以理解为先全部都选,然后删掉一些位置。

P2762 太空飞行计划问题

类似最大权闭合子图。首先选中全部实验的价值。直接源点向实验连边,容量为对应收益,仪器向汇点连边,容量为对应费用。

实验与依赖的仪器之间连边,容量为 \(\infty\)

求出最小割,割掉实验的边即不选这个实验,割掉仪器的边即要选这个仪器。于是总价值减去最小割即可。

P1361 小M的作物

二选一的模型,转最小割。选的价值最大,那么割掉的不选的价值最小,符合最小割。那么首先把所有价值都算上。

对于一个作物 \(x\),分别向源汇点连容量为对应价值的边。割掉对应的边表示不选它在对应的区域种,必然恰好有一条边被割。

然后描述一个集合中的作物都种在一起会得到的价值。比如割掉 \(x\) 到汇点的边,那么同时也要割掉对应集合产生贡献代表的边。那么对每个限制的集合建两个虚点,一个从源点向其连容量为价值的边,然后再向对应作物连容量为 \(\infty\) 的边。另一个向汇点连边,是类似的。

这样就很好地描述了集合的限制。跑最小割,用总价值减去最小割即可。

P2770 航空路线问题

对每个城市建一个点,再拆点,两点间连容量为 \(1\) 的边限制只能经过一次。用两条流量路径描述两条仅在 \(1,n\) 处相交的路径。\(1/n\) 拆成的两点间连容量为 \(2\) 的边。原图中的边直接出点向入点连边,容量为 \(1\) 或者 \(\infty\),这里不会影响答案。然后 \(S\)\(1\) 的入点连边,\(n\) 的出点向 \(T\) 连边,跑最大流。如果最大流不为 \(2\),说明无解。

现在要构造解,直接在残量网络上沿着流的痕迹 DFS 即可。

P2766 最长不下降子序列问题

第一问直接暴力 DP 即可。顺带求出 \(f_i\) 表示以位置 \(i\) 结尾的最长不下降子序列长度。

第二问拆点连容量为 \(1\) 的边限制一个点只能取一次。从 \(S\) 向每个 \(f_i=1\) 的位置连容量为 \(\infty\) 的边,从 \(f_i=s\) 的位置向 \(T\) 连容量为 \(\infty\) 的边。然后点之间按 DP 的转移连边,即若 \(j<i\land a_j\le a_i\land f_i=f_j+1\),那么连边,容量为 \(1\)(若为 \(\infty\) 在第三问要多判一点,从 \(1\) 转移出来的会错)。然后跑最大流即可。

第三问将 \(1\)\(n\) 拆出来的两点之间的容量改成 \(\infty\) 即可。

P4012 深海机器人问题

对于一个出发点,从源点向其连边,容量为机器人个数。对于一个结束点,向汇点连边,容量为机器人个数。用最大流限制每个机器人必须到结束点。

现在就是要求最大收益。对于一条边,两端连容量为 \(1\),费用为收益的边,限制只能获利一次。再在两端连容量为 \(\infty\),费用为 \(0\) 的边,表示后来的随便走,不产生收益。

跑最大费用最大流即可。可以对边权取反,仍然跑最小费用最大流。

P4013 数字梯形问题

用流量限制可经过次数,求最大费用。每个位置拆点。

第一问,拆点后两点间容量为 \(1\),边权为 \(0\)。相邻的点连边,容量为 \(1\),边权为 \(0\)\(S\) 向第一行连边,容量为 \(1\),费用为指向的点的价值,\(T\) 类似。相邻点之间连边,类似 \(S\) 连边。直接最大费用最大流。

第二问,将拆点得到的两点间的容量设为 \(\infty\),然后与 \(T\) 相连的边的容量设为 \(\infty\) 即可。

第三问,将点与点之间互相连的边的容量设为 \(\infty\) 即可。

P3356 火星探险问题

还是每个点拆点,非障碍的点都可以多次经过,连容量为 \(\infty\),边权为 \(0\) 的点。有岩石样本的点只能收益一次,再连一条容量为 \(1\),费用为 \(1\) 的边。相邻的两个点要是都不是障碍,那么还要出点向入点连容量为 \(\infty\),费用为 \(0\) 的边。跑最大费用最大流即可。

输出路径还是在残量网络上沿着流的痕迹走就行。小模拟。

P2764 最小路径覆盖问题

考虑转化。将 DAG 上每个点拆为入点和出点。DAG 上的 \((u,v)\) 对应连 \((u_{\text{out}},v_{\text{in}})\)。可以发现这是二分图。一开始将每个点视作单独的一条路径,\(u_{\text{out}}\)\(v_{\text{in}}\) 匹配相当于合并了两条路径,使路径数减一。

于是答案为 \(n-\text{最大匹配}\)。找方案就是在二分图上找匹配点,然后记录路径即可。可能要拓扑排序。

P2765 魔术球问题

直接枚举会有多少个球。新加入一个球就连对应的边。

如何连边?如果两个数相加为完全平方数,就小的往大的连一条边。连出来的必然是一张 DAG,所需的最少柱子数量就是最小路径覆盖。新加点后不必复原网络,只要不断增广即可。

所需柱子超过限制时,最后一次加入的点必然没有增广,于是残量网络就是刚好达到限制时的残量网络加上新点。类似最小路径覆盖问题记录方案即可。

P2053 [SCOI2007] 修车

费用提前计算的想法。首先转化为最小化总时间。

将一个人拆成 \(n\) 个点,每个点表示修倒数第 \(i\) 辆车之后的这个人。假设这个人修了若干辆车,设倒数第 \(i\) 辆车用时为 \(t\),那么一共有 \(i\) 个车主在等这个人,于是对总等待时间的贡献为 \(i\cdot t\)

于是可以建模,第 \(i\) 辆车向第 \(j\) 个人的第 \(k\) 个状态连边,表示 \(j\) 倒数第 \(k\) 个修 \(i\)。容量为 \(1\),边权为 \(k\cdot t\)。用流量限制每辆车都被修了,源点向每辆车连容量为 \(1\),费用为 \(0\) 的边,人的每个状态向汇点同理连边即可。

直接最小费用最大流。

P2050 [NOI2012] 美食节

类似上一道题。但是算算复杂度发现不太行。发现上一道题的建模中有很多点不会用到,一个人的状态只会被用到一个前缀。

于是这道题动态加点,每次增广后判断一个人现有的状态是否被用完,被用完了就新加一个状态。还是最小费用最大流即可。

P3358 最长k可重区间集问题

一个点不超过 \(k\),即对于每个限制的端点都不超过 \(k\)。所以可以先离散化。用流量限制一个点不能被覆盖 \(k\) 次。

\(S\) 向数轴起点连容量为 \(k\),费用为 \(0\) 的边,\(T\) 同理。每个区间连容量为 \(1\),费用为长度。于是最大费用最大流。

P3980 [NOI2008] 志愿者招募

类似上一道题,但是限制改成大于等于。转化题意,设总共有 \(X\) 个人,第 \(i\) 天至少 \(a_i\) 个人工作可以转化为至多 \(X-a_i\) 个人休息。于是对每天拆点,容量为 \(X-a_i\),费用为 \(0\),流量表示这一天有多少人休息。从 \(s_i\)\(t_i+1\) 连容量为 \(\infty\),费用为 \(c_i\) 的边,流量表示有这么多人不休息,在第 \(t_i+1\) 天恢复休息。

跑最小费用最大流即可。还有线性规划做法。

P3153 [CQOI2009] 跳舞

拆点,男生拆成与喜欢的人跳舞的点 \(A\) 和与不喜欢的人跳舞的点 \(B\),女生同理。向喜欢的人和不喜欢的人连边,容量都是 \(1\),限制只能跳一次。

现在要找的其实是跳舞最少的人最多跳了几次。这个可以二分,转为判定。

对每个男生,从 \(S\) 向其连容量为 \(mid\) 的边;对每个女生,向 \(T\) 连容量为 \(mid\) 的边。如果能满流,即得到的最大流恰好为 \(n\cdot mid\) ,那么 \(mid\) 合法,否则不合法。

每次二分重新建图跑最大流就行。

P5458 [BJOI2016] 水晶

注意到这是二维平面,所以三维坐标中一维是冗余的。可以发现将原题坐标 \((x,y,z)\) 改为 \((x-z,y-z)\) 即可唯一确定一个点。

给出的两种共振都含有三个点,分别模 \(3\)\(0/1/2\),且 \(b\)共振中 \(0\) 在中间,\(a\) 共振可以视作 \(0\) 在中间。

将各个水晶按模 \(3\) 的余数向相邻的水晶连边。具体地,首先将所有水晶的收益算上,然后减去建出的图的最小割就是答案。

将每个水晶拆点,两点间容量为其收益。余 \(2\) 的点向余 \(0\) 的点连容量为 \(\infty\) 的边,余 \(0\) 的点向余 \(1\) 的点连容量为 \(\infty\) 的边。\(S\) 向余 \(2\) 的点连容量为 \(\infty\) 的边,余 \(1\) 的点向 \(T\) 连容量为 \(\infty\) 的边。

跑最大流即可。这样刻画了每个共振的关系,一定会割掉若干点破坏所有共振。

P3305 [SDOI2013] 费用流

观察到 Bob 一定会将所有费用放在流量最大的一条边上。于是就是要最小化流量最大的一条边的流量。二分之,注意加上这个限制后的流量可能是浮点数。

每次二分重新建图,重赋容量即可。

P2153 [SDOI2009] 晨跑

每个点拆点,连容量为 \(1\),费用为 \(0\) 的边,限制只能经过一次。\(1,n\) 拆出来的两点之间的容量设置为 \(\infty\),因为可以重复经过。

\(S\)\(1\) 连容量为 \(\infty\),费用为 \(0\) 的边,从 \(n\)\(T\) 连容量为 \(\infty\),费用为 \(0\) 的边。原图中的边就从出点向入点连容量为 \(\infty\),费用为边权的边(这里的容量也能为 \(1\),但是要对与 \(1,n\) 相连的边特殊处理)。

然后直接跑最小费用最大流就行。

P4298 [CTSC2008] 祭祀

用 Dilworth 定理,最长反链等于最小可重路径覆盖。于是第一问就是 DAG 的最小可重路径覆盖。

先传递闭包,对传递闭包后的可达关系建图,然后就是最小不可重路径覆盖,因为原图上本来相交的路径,可以在新图上找到跳过交点的一条路径。于是就是新图上的最小不可重路径覆盖。

然后先求第三问。如果钦定一个点选中,那么所有可达它以及它可达的点都不能被选中。枚举钦定选中的点,再重新建图,删去它可达以及可达它的点,再跑第一问。如果剩下的最长反链恰好少了一,那么说明这个点可以在答案中。

最后求第二问,对于每一类可以选的点,它只是和它可达以及可达它的可选点互斥。不妨在每类点中选编号最小的,即可构造出一组方案。

posted @ 2025-06-05 08:57  RandomShuffle  阅读(12)  评论(0)    收藏  举报