kkio。|

_kkio

园龄:1年7个月粉丝:6关注:1

模拟费用流与反悔贪心小记

0. 一些约定

若无特殊说明,我们约定:

  1. (u,v,c,w) 代表一条 uv,容量为 c,费用为 w 的边。(c,w) 代表容量为 c,费用为 w 的边。
  2. S 代表源点,T 代表汇点。

1. 概括

模拟费用流与反悔贪心有着非常相似的思想,有些时候可以互相代替。无论是哪种解法,都能通过反悔决策增量地维护答案,因此有时可以解决动态规划或朴素贪心难以解决的问题。

2. 性质与基本思路

  • 费用流模型关于流量具有凸性,可以通过费用流模型证明 wqs 二分的可行性。

  • 在一些简单费用流模型里,不妨观察增广路和负环形式,简化费用流计算。时刻注意,在正常的费用流中,增广路是不会有环的。

  • 在部分费用流模型里,可以将费用流退流决策一起放入计算中。

  • 在模拟 EK 算法时,如果数据允许,可以尝试增量加边。

  • 反悔贪心的反悔决策如果不能用增量比较,尝试用朴素的贪心策略进行反悔。

  • 反悔贪心可以用双向链表,优先队列维护差值等方式进行连续反悔。

  • 在反悔决策不明朗时,尝试将反悔也当成可行决策。

  • 反悔时的增量可以看情况选择,有时不一定是一个一个增加的。

3. 模拟费用流例题

  • 类型一:费用流模型证明 wqs 二分可行性。

Raper

发现这个问题如果直接反悔贪心有三种决策,分别是组一对新的 AB,替换一个 B,或者替换一对 AB 。在 k 的限制下直接做是不容易的。

费用流建模是容易的。

有了建模之后就有凸性了,考虑给 ai 带权二分,解除了 k 的限制后剩下部分的反悔毙掉了替换一对 AB 这个操作,剩下两个操作可以直接反悔。

种树

解除限制之后的 dp 非常典,现在考虑如何建模。

将每个坑的间隔看成一个点,每个坑成一条边,有公共坑的间隔连一条权为坑的权的边,边容量都是 1,分成二分图即可。

  • 类型二:简化费用流计算。

雪灾与外卖

uoj 差评榜 rk3(好像是),鉴定为蒸。

这个题可以用反悔贪心解释:

我们给两个堆,堆 A 表示拆出一个送餐员的代价,堆 B 表示多一个餐厅的代价。从小到大加入,保证堆中决策坐标都比当前小。

当加入一个餐厅时:

  1. 寻找一个未匹配的送餐员,抑或是寻找一个可以替换的已在匹配中的餐厅。从堆 A 中找,假设代价是 W,则贡献是 yi+wi+W。如果撤销该决策,多出这个餐厅,代价为 2yiW,加入到 B 中,再将替换这个餐厅的贡献 yiwi 加入堆 A
  2. 否则将 yi+wi 加入 B 中。

当加入一个送餐员时:

  1. 寻找一个可以匹配的餐厅,抑或寻找一个可以替换的已在匹配中的送餐员。从 B 中找,假设代价是 W,则贡献是 xi+W。如果撤销此决策,多出这个送餐员,代价为 2xiW,加入到堆 A 中。
  2. 否则将 xi 加入到 A 中。

这里有一个细节,那就是为了让它满流,我们提前往 B 中增加代价为 +,可用次数也为 + 的一个餐厅即可。

这里告诉我们反悔贪心的另一个套路,那就是将反悔与普通决策同质化。但是这里我要引出一个很厉害的费用流模型来解释这个反悔贪心。

先上图:

这张图的源点是 0,汇点是 7。每个坐标拆成 inoutinout 连一条费用 2x 的边。in 从大往小,out 从小往大连 0 边,若有送餐员,从 S 向对应的 in 连费用为 0,容量为 1 的边,若有餐厅,从对应的 out 连费用为 wi ,容量为 ci 的边。可以发现,这张图求解的最小费用最大流即为原问题的解。

现在考虑模拟 EK 算法,先单路增广 0367 这条路径,变成:

代价即为 yx+wi,设 W=y+wi,此时形成一个环,假如这个环是负的,消圈后变成:

整体上,你加上了yj+wjW 的代价,多了一条可能的 14567 的代价为 2yj+W 的增广路,跟上次一样的,以后可能反悔这条 wj+yj 的边。这神似我们之前的反悔贪心,其实本质是一样的,分析另一种情况应该也能得出相同结论。

为什么要多讲一个费用流模型,因为接下来还有用这个模型解释的题(在反悔贪心那儿)。

Olympiad in Programming and Sports

这题数据范围其实可以直接费用流解,但是模拟费用流也是可以的。

本题的费用流模型这么建:建一个二分图,下部 n 个点,上部 2 个点,容量与费用显然。考虑模拟 EK 算法,每次寻找一条增广路,这条增广路的形式只有四种(以下用 A,B 来描述上部两点):

  1. SAiT
  2. SBiT
  3. SAiBjT
  4. SBiAjT

之外的增广路都是不优的(大概画一画,发现因为只有两个点,其他的都会形成负环,不可能出现)。

S,T 之间的连边费用均为 0 直接忽略掉,拿四个堆维护即可。

另一种很有启示的思路:考虑一条一条加入 SA,B 的边,我们先将 SA 的边全部加完。我们将最优的几个 ai 匹配,一定是加完 SA 边后的最佳匹配。

之后我们继续加入 SB 的边,那么增广路有两种可能:

  1. SBiT
  2. SBiAjT

剩下的增广都不经过新加的 SB 的边,不考虑,这样我们就只用三个堆了。

这也告诉我们,在一些模型里,尝试提前增广一类型的边可以简化问题。下一道题就是这样。

上一道题能不能也这样做?回去再想想。

蔬菜

蔬菜越来越多,我该怎么办?

嘴巴一下:

给每天建个点,往 T(m,0) 的边,每个蔬菜也建点,这一步建图是简单的。

考虑倒推,每天加入当前的 m 条边,这个费用流性质很好,是个可以直接用堆玩的贪心。

好的你现在会 q(n+mp)logn 复杂度了,我们考虑做多测,其实就是要从最后一天开始退流。发现对于最后一条边,你啥都能退,直接拿小根堆把所有东西都扔进去,做完了。

有点嘴巴,详细说说。

考虑先建模,每天建一个点,往 T(m,0) 边,第 i+1 天往第 i 天连 (+,0) 边,对于每个蔬菜,我们也建一个点(其实可以不建),从 S 连一条 (1,si+ai),连一条 (ci1,ai) ,从蔬菜刚好流失的那天开始,往每天连容量为当天损失蔬菜数量的边。

直接跑就是对的。如果我们做单测的话可以直接从那天开始,一次一天一天往前走,每天增广当前的 m 条边,容易发现增广路形式只有一种,直接用堆存可行的增广路即可。

如果多测的话,我们先用跑出 p=105 的答案,那么我们就知道了我们要选哪些蔬菜。如果要往前推,要把当天的流退完,相当于找 TS 的增广路。同样是只有一种增广路,唯一的区别在于,你不用在中途加入新的增广路,所有增广路一开始就已经可以流了。同样用堆存就行了。

序列

如果你在考场上一眼瞪出可以费用流建模,就已经有二分套二分的 64 的高分了。然而想拿满,光靠这个还不够。具体考虑如何建模。

建模如下:建一张二分图,左右部分别当 a,b 连,要求 L 个相同的位置,相当于自由选择不同的位置至多 KL 个。建两个虚点,中间连一容量 KL 的边,两个点再分别向 a,b 连边即可。对于剩下的,我们限制他们必须选相同位置,a,b 想通过位置连边即可。流量固定为 K

仍然考虑优先增广较为特殊的边,也就是那两个虚点中间的边。很明显,直接找到 ab 中最大那几个就是最优。

继续增广,现在只能增广 a,b 对应位置相连的边了。一下我们称 iai 对应的点,ibi 对应的点,PQ 对应两个虚点。

增广路有四种:

  1. SiiT
  2. SiPjjT
  3. SiiQjT
  4. SiPjjQkT

5 个或 6 个堆维护这玩意就行了,其余的增广路都带个环。

在重做这道题的过程中,得到了一点经验,那就是在在手动寻找增广路径比较困难时,一定要记得使用小数据对拍 + 手玩,往往可以拍出漏掉的增广路。还是那句话,让程序帮你做麻烦的事情。

4. 反悔贪心例题

  • 类型一:尝试使用普通贪心策略反悔。

Exhausted?

如果只有 LR 的限制,可以直接排序后贪心。如果限制同时出现,我们考虑反悔,在满足一边取到最优的情况下使另一边最优。

L 一维排序,然后从小到大做第一步贪心。此时我们保证了新加入的人一定可以替换掉之前的人,而如果当前的人能换出一个更小的 R 就换。

剩下没配上的人和位置再按 R 贪心。

听上去挺嘴巴的,但是确实没问题。

  • 类型二:将反悔决策同质化。

征服世界

雪灾与外卖的严格加强版,把数轴改成了树。

这题用网络流模型不好分析,但是也不是不行,先考虑反悔贪心的想法。

拆贡献成 disa+disb2dislca

考虑雪灾与外卖的类似分析,两个堆 A,B 分别表示多出一个军队的代价和多出一个驻军地点的代价。

在每个节点上往 A 加入 XudisaYudisb,之后考虑每次从 A,B 中拿出一个军队和驻军地点,设贡献分别为 W1,W2

那么如果连接他们的贡献为 W1+W22disu,如果要反悔其中的军队,贡献为 2disW1,多一个驻军地点,加入 B,如果反悔其中的驻军地点,贡献为 2disW2,加入 A

直接拿配对堆暴力向上合并就行了,注意回收内存。

如果要用模拟费用流解释的话,大致思路就是,仿照雪灾与外卖拆点,in 向祖先 in 连边,out 向后代 out 连边,然后分析费用流负环情况,发现反悔后产生的反悔路径如果要形成新的负环,一定从当前节点也就是 lca 处往上或往下,否则不是最优的。然后就像雪灾与外卖一样加入新的反悔决策即可。

如果这题不是树而是 DAG 的话,能有同样的优化方法吗?其实在原来的建模越来越接近一般图的情况下,模拟费用流越接近普通的费用流算法。所以在反悔贪心时,也可以用费用流建模考虑反悔贪心的可行性。

upd:貌似 DAG 的话跟最小链覆盖差不多,那应该寄了(

本文作者:_kkio

本文链接:https://www.cnblogs.com/hikkio/p/17847117.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   _kkio  阅读(305)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起