zoukankan      html  css  js  c++  java
  • 网络流 24 题 题解

    去年看 wll24T 的时候还是除了那个错题是黑题,其他全是紫题。现在咋有 4 个蓝题了?真就被透析了?太害怕了。

    P1251 - 餐巾计划问题

    u1s1 好多有一些思维难度的网络流都可以上下界网络流直接秒啊……

    我们考虑给每一天搞一个点,然后必须流入恰好 (r_i) 个单位的流量,这个可以点边转化,拆点然后上下界。

    然后从 (s) 流到某个点表示买来这么多,某个点流到 (t) 表示扔掉了。然后点之间相连表示可以送到快洗 / 慢洗店将左端的天留下来的纸在右端的天用。那么我们显然可以构出一个边数平方(就是点们可能两两相连)的图,但这样吃不消。不难发现每个点的出边都是个后缀,再建一排虚拟节点后缀预处理一下即可。

    然后跑有源汇上下界最小费用可行流即可,大概是 (n=3N,m=10N) 这样子。没有负环,因为是 DAG。

    code

    P2754 - 星际转移问题

    先对题目描述吐个槽:「每一艘太空船从一个太空站驶往任一太空站耗时均为 (1)」指的是每到一个太空站必须立刻走,而不可以停留……这害我想了好长时间。

    注意到数据范围这么小,我们考虑枚举答案。如果有解的话那么最坏显然是一个特定的飞船每个循环带一个人,那就是 (mathrm O(nk))。又显然可以二分答案来优化。

    check 的话,考虑建网络流。直接建的话杂乱无章,可能导致时间倒流,于是我们强行对每个点拆出多个时刻,然后分层建图。这就很清晰了,(s) 流向第 (0) 秒的地球容量为 (k),然后相邻层之间就按照飞船当前应该从哪儿到哪儿建(容量为飞船容量),另外还可以停留(水平连边,容量 (+infty)),最后一秒的月球流向 (t),看是否满流。点数大概是 (mathrm O!left(n^2k ight)),边数 (mathrm O!left(n^2k+mnk ight))

    code

    P2756 - 飞行员配对方案问题

    就是个二分图最大匹配的板子……需要输出方案,就输出残量为 (0) 的有意义的边。

    code

    P2761 - 软件补丁问题

    这根本就不是网络流嘛……

    网络流做废掉了,这么自然的一个状压都想不到了。考虑在状态和状态连边,那么答案显然是全集到空集的最短路。

    但是 (n=2^{20},m=2^{20} imes100),啥最短路算法都跑不了。但这确实是正解(服了,什么绝世垃圾题)……因为边数非常不满。然后还不能把边存下来,会 MLE,需要临场枚举。

    code

    P2762 - 太空飞行计划问题

    最大权闭合子图模板题。就实验连向仪器,然后求最大权闭合子图。

    输出方案的话,就是输出最小割的包含 (s) 的那个点集。根据最大流最小割定理显然有,求完最大流之后只看还剩残量的边,那么包含 (s) 的连通分量就是最小割中包含 (s) 的点集。

    code

    P2763 - 试题库问题

    我想说,这题真的是太太太太太太太太太太水了。不知道是如何评到紫题的。

    就套路的建四排点,第一排 (s),第二排试题,第三排类型,第四排 (t)。就连边,把试题往类型贡献。最后看汇连的边们是否满流即可。方案随便输。

    code

    P2764 - 最小路径覆盖问题

    最小不相交路径覆盖模板题。输出方案的话,就根据匹配情况记录一下每个点在所在路径中的入和出,然后对每个没有入的点都往后链一遍输出一下即可。

    code

    P2765 - 魔术球问题

    也是有通项的,但是现在先不管。(因为这个是模拟赛原题,补的时候再证一下)

    考虑二分答案。判定的话,我们考虑建一个流,每条流表示一根柱子。然后就源连向每个点,其中出去的总流量不能超过柱子数,这个可以点边转化。然后和等于完全平方数的两个数,小的连向大的,最后汇起来。唯一的要求就是每个点都必须被流恰好一次,这个可以点边转化然后上下界。

    统计方案就跟最小路径覆盖相似。

    打个表发现答案大概是平方级的,不慌。

    code

    P2766 - 最长不下降子序列问题

    第一问直接 DP 好了,当然你写费用流我也不拦你。

    第二三问显然最大流,每个点访问次数的事情就点边转化然后设容量。但如何强制每条 (s o t) 流都长度最大呢?考虑 DP 过程,必须是合法转移对之间才能有边,这样就可以了。

    code

    P2770 - 航空路线问题

    我是 sb 吗,我咋就想不到,倒过来走等价于正过来走呢。

    那这样就很简单了。只需要找两条 (s o t) 路径,然后唯一的要求就是中间那些点经过次数 (leq1)(1,n) 经过次数 (leq 2)。那就随便点边转化即可。然后每经过一个点都会有一个贡献,这个停留在流量上就是不可做的了,不难想到费用流,在点边转化的边上搞个费用,求最大费用最大流。

    输出路径也不难,就找到两条一条正着一条倒着。

    最要命的是,倒过来竟然可以直接 (n o 1)。这个需要特判一下,最大流为 (1) 的时候也可以。

    code

    P2774 - 方格取数问题

    最小割……是我想不到的东西,因为这玩意本来也没刷几题,不认识。

    显然可以奇偶建二分图。然后考虑该如何表示相邻两个不能共存这个东西。「不能共存」其实是最小割的一个标志,一般是在两个不能共存的东西之间连边,然后一个连 (s),一个连 (t),中间连一条割不断的无穷边。最终目标是要使得 (s,t) 不连通,也就是这两个东西不能共存了,一共存就连通了。「集合划分模型」正是一种特殊的「不能共存」,即属于两种集合的状态不能共存。

    回到这题,那就很简单了,直接建然后求最小割就可以了。

    换一种理解方式。刚看到认为是一个二分图最大权独立集。哎呀 wd,这玩意我可没学过。细想一下,由于独立集和点覆盖形成双射,那么显然有最大权独立集等于点权和减去最小权点覆盖。但是最小权点覆盖这玩意咋搞呢,还能链到匹配吗?不能了,于是放弃了。

    但其实独立集这玩意本质就是个「不能共存」,所以可以最小割直接切……然后最小权点覆盖也能求了……然后便发现了新大陆,之前学这玩意的时候证最大匹配等于最小点覆盖似乎挺不直观的,现在发现可以直接一眼证独立集和最小割之间的关系,再独立集 -> 点覆盖,最小割 -> 最大流 -> 匹配。

    最小割的一个迷人的地方就是可以把一些看似费用流的东西用不带费用网络流来做。

    code

    P2775 - 机器人路径规划问题

    错题。

    P3254 - 圆桌问题

    也是挺板的一题。也是建两排点表示代表(不同意的代表请举手。没有!没有!没有!)和桌子,然后具体连边方式就不讲了,太水了。

    最后如果满流就 ok 并且输出方案。

    code

    P3355 - 骑士共存问题

    二分图基本操作?

    显然是建图然后求最大独立集。但是 zszz 一般图最大独立集是不可做的。观察到两个点互相攻击的一个必要条件是它们的行加列的奇偶性不等。于是就可以这样经典地按奇偶性建个二分图即可。

    就最大匹配等于最小点覆盖,最小点覆盖又和最大独立集互补。

    code

    P3356 - 火星探险问题

    终于轮到我说这句话了:……有什么意义吗

    跟深海机器人那题高度相似。只不过这题改成了点上的贡献,就点边转化然后连两条边即可,一条有费用,一条没费用。然后这题新增了障碍物,不能建点。还有这题只有单源单汇。

    输出方案就一边增广一边倒着输出,写起来比较方便。

    code

    P3357 - 最长k可重线段集问题

    ………………有什么意义吗,和 P3358 一模一样,只不过长度计算方式改掉了。

    然后这题有一个小坑点:两条垂直的在同一竖直线上的线段是算相交的。很自然的想到,把它们稍稍歪斜一点角度,把左右端点各 (mp0.1)。但这样又会导致其他线段与竖直线段相交,那么其他线段左右端点各 (pm 1) 即可,往里缩一点。然后这个浮点数的精度处理我还不会,可以扩大个 (10) 倍这样子。

    code

    P3358 - 最长k可重区间集问题

    提供一个跟大家不太一样且同等优秀的做法吧,并且我觉得很容易理解(至少对我来说)。

    首先我们需要换一个角度思考。问题等价于,选出 (k) 个区间集,其中每个区间集两两不相交。这个事情不显然,事实上它是本题最难想到的一个点。

    然后就非常好办了。我们考虑把 (s) 连向每个点(区间),每个点连向 (t) 表示每个点都可以作为路径的起始点。然后把所有不相交的区间对给连起来,只从右往左连(当然你也可以从左往右),因为为了避环。然后其他的一些限制比如选 (k) 个路径,就设一个超源连向 (s) 并注入流量 (k)。对于每个点不仅有费用,还有流量 (leq 1) 的限制,于是点边转化。跑最大费用可行流即可,然后显然最大费用可行流是一个最大流。

    这样边数是平方级别的,应该能过的去了。但是发现,对于每个点连出的点的集合,是一个关于右端点的前缀。于是很套路的前缀虚拟节点优化建图一下就线性了。

    code

    P4009 - 汽车加油行驶问题

    网络流做废掉了,现在看到「从起点出发到达终点所付的最小费用」都看不出来是最短路了…………

    建图就看图写话,看题面写代码吧。考虑把每个点拆成 (k+1) 个点表示还可以走多少步,边上的费用照建,点上的费用就点边转化。一个显然的结论是,只会在空白位置新建加油站并加油最多一次,那么就不用担心了。

    细想一下发现这题费用流和最短路是等价的,因为最大流显然为 (1),那么就增广恰好一次,也就是求恰好一次最短路。但是本题 (|V|=mathrm O(|E|)=mathrm O!left(n^2k ight)),费用流的话 SPFA 过不去,只能 Dijkstra。

    code

    P4011 - 孤岛营救问题

    很好,这次我终于看到 ((1,1) o (n,m)) 的最小时间而想到最短路了,魂还在。

    注意到 (p) 非常小,很自然的想到把手头钥匙的 bitmask 和当前位置压在一起形成一个状态。然后状态之间的连边显然,需要判一下是否可连。然后由于会在节点处拿钥匙,所以还要点边转化一下,在点内部进行钥匙 bitmask 的转移。

    然后点边转化得到的边不能算路程,权为 (0);真实的边权为 (1)。那就 01Dijkstra(可能在某些人的口中叫 01bfs?)一下即可。

    code

    P4012 - 深海机器人问题

    题目啥意思啊,读不懂。

    我们注意到价值是在边上贡献的,容易想到费用流。这是一个最最直观的建图方式,即一条 (s o t) 流表示一个机器人的行进路线。就在网格上连边就可以了。然后由于一条边最多被算一次价值,所以连一条 (c=1,w=x),连一条 (c=+infty,w=0)。然后有多源多汇,就建超源超汇搞一下即可,容量分别是给出的 (k,r)

    然后求最大费用可行流。但是显然这题最优情况是每个机器人都走一条路径,那么最大费用可行流一定是最大流,于是只要求最大费用最大流即可,写的简单一点。SPFA 就稍微改一下不等号方向和极限值即可。

    code

    P4013 - 数字梯形问题

    数字处有价值,点边转化。然后随便建一个图,(s) 向上面一排每个节点连 (1) 边,最后求最大费用可行流(本题中等于最大费用最大流)。三个小问分别对应:点边容量 (1) 边容量 (1)、点边容量 (+infty) 边容量 (1)、点边容量 (+infty) 边容量 (+infty)。CV 三遍跑三次费用流即可。

    code

    P4014 - 分配问题

    ???二分图最优匹配(最小权最大匹配 & 最大权最大匹配)模板题?咋回事 wll24T 这么多板子?

    把 P4015 代码改一下就好了。

    code

    P4015 - 运输问题

    yet another 费用流究极模板题?

    依旧是套路地建两排。中间边的费用就是 (c) 数组啦。求最小费用最大流和最大费用最大流就好啦。就把板子 CV 一遍改一下。

    code

    P4016 - 负载平衡问题

    如果费用流没有模板题的话,我愿称此题为费用流模板题。

    考虑建两排点,第一排表示初始仓库,第二排表示运完之后的仓库。那么 (s) 连向第一排容量为 (a_i),第二排连向 (t) 容量为平均数(这里没有说平均数是整数,但实际上是的,差评),费用都为 (0)。然后仓库与仓库之间,就随意流,费用是距离。求个最小费用最大流即可。

    还有数学方法,不管了。

    code

  • 相关阅读:
    Parcel与Parcelable剖析
    Binder文集
    Charles 使用教程
    AsyncTask
    Android 编译时注解
    scanf(),gets(),getchar()
    银行家算法
    最长公共子序列(LCS)问题
    动态规划 求解数字三角形最大值
    参数 存在二维数组
  • 原文地址:https://www.cnblogs.com/ycx-akioi/p/wll24t.html
Copyright © 2011-2022 走看看