[学习笔记]当网络流遇上了上下界

〇、前言

每次到 \(\sf TryMyEdge\) 和同学们的名场面,战线就会太长,我就跟不上了......

然后我就只能脱离战线了 被迫当逃兵 TAT。

还有一些学习使用的资料 战线过长,资源补给不到位,只能自给自足了

Menci's Blog\(\text{NOI Ag}\) 的学长.

至于一些代码什么的,能补就补,补不上就......就这样吧。

壹、无源汇可行流

1.1.问题描述

我们要解决的问题是:

\(n\) 个点 \(m\) 条边,每条边有个流量下界和上界,要求图中每条边都要达到下界,不能超过上界,无源汇点,求这样的方案。

1.2.建图

这种问题怎么搞?实际上我们只需要这样建图,定义一个炒鸡源点 \(ss\),炒鸡汇点 \(tt\),对于一条边 \(e=\lang u,v\rang,flow(e)\in [low,c]\),这样连

graph LR subgraph 1.2. ss((ss)) u((u)) v((v)) tt((tt)) ss --> |low|v u --> |c-low|v u --> |low|tt end

对于我们新建出来的图直接跑从 \(ss\)\(tt\) 的最大流就可以了,如果对于每条 \(ss\rightarrow u\) 的点,以及 \(v\rightarrow tt\) 的点都跑满了,就是存在解的,解该怎么找就不多说了。

但是为什么这样是可行的呢?从含义上讲,由于每条边至少都要向 \(v\) 流一个 \(low\) 的流,我们就先强制满足这样的要求,而对于 \(u\),它至少要流出 \(low\),我们也让它满足这样的要求,而这条边剩下的一些容量 \(c-low\),就放在网络里面自行调整。如果把 \(ss,tt\) 想象成 传送门/中转站 的话,可能会更形象。

1.3.一些优化

考虑到我们有 \(m\) 条边,每条边要搞出 \(3\) 条额外边,但是我们很有可能搞出这样的情况

graph LR subgraph 1.3. ss((ss)) u((u)) tt((tt)) ss --> |a|u ss --> |b|u u --> |x|tt u --> |y|tt end

实际上我们可以将 \(ss\rightarrow u\) 的两条权值分别为 \(a,b\) 的边合并成一条权值为 \(a+b\) 的边,对于 \(u\rightarrow tt\) 亦是如此,更厉害地,我们可以将 \(a,b,x,y\) 都合并,分两种情况讨论:

  1. \(a+b\ge x+y\),那么我们只需连 \(ss\rightarrow u\),容量为 \(a+b-x-y\)
  2. \(a+b< x+y\),那么我们只需连 \(u\rightarrow tt\),容量为 \(x+y-a-b\)

然后直接跑网络流最大流,判断所有从 \(ss\) 出,入 \(tt\) 的边是否满流即可,要构造方案也很简单。

1.4.代码

传送门 to LOJ

贰、有源汇可行流

2.1.问题描述

和 1.1. 差不多,多了个源点 \(s\) 和汇点 \(t\).

2.2.建图

考虑如果存在这样的可行流,那么就有从 \(s\) 出去一些流,进入 \(t\) 一些流,如果我们将 \(t\rightarrow s\) 连一条 \(+\infty\) 的边,流进 \(t\) 的流又流回 \(s\),那这不就是无源汇可行流了吗?

所以,解决办法就是:先像 壹 中连边,然后再连 \(t\rightarrow s\) 的边,容量为 \(+\infty\),然后跑最大流。

最后,原图上\(s\)\(t\) 的流量就是建出的图上 \(t\rightarrow s\) 的流量。

叁、可行最大流

3.1.问题描述

建立在 2.1. 的基础上,求在满足上下界要求的情况下,从 \(s\)\(t\) 的最大流。

3.2.转化

最大流不是流?所以我们要先用 贰 判断是否有解。

如果有解,那么我们当前所得到了一个可行流,这个流中,满足了每条边的下界,对于这个烂摊子我们怎么办呢......

直!接!从!\(s\)!向!\(t\)!增!广!

这个是什么意思呢?本来我们的源汇点是 \(ss\)\(tt\),但是跑完之后我们发现它们俩没用了,因为如果存在可行流,我们现在就要求的是最大流,由于 \(ss\) 没有入边,\(tt\) 没有出边,所以我们直接增广 \(s\rightarrow t\) 的时候不会将他们俩考虑进去,换句话说,我们不会把边的下界都破坏掉 —— 因为从 \(ss\) 连出和连入 \(tt\) 的边都是保证下界的,我们不会增广他们即不会破坏他们的边,进一步说不会破坏所有边的下界保证。

所以先跑可行流,如果有就再在这个烂摊子上跑从 \(s\)\(t\)\(\tt dinic\) 就可以了。

3.3.代码

传送门 to LOJ

肆、可行最小流

4.1.问题描述

和 3.1. 没啥区别,求最小流就是了。

4.2.转化

类似 3.2. 我们先求可行流,得到一个烂摊子,然后,我们只需要跑反向最大流,用可行流减去反向最大流就可以了......但是注意需要把之前 \(t\rightarrow s\)\(+\infty\) 的边去掉,不然就嘿嘿嘿了。

很简单的转化。

4.3.代码

传送门 to LOJ

伍、无负环可行费用流

5.1.无源汇可行可行最小费用流

考虑模仿 1.2. 的建图,对于一条边 \(\lang u,v,w,c\rang,flow\in [low,c]\),我们这样建

graph LR subgraph 5.1. ss((ss)) tt((tt)) u((u)) v((v)) ss-->|w/low|v u-->|w/low|tt u-->|w/c-low|v end

然后直接跑从 \(ss\)\(tt\) 的最小费用最大流即可。

5.2.有源汇可行最小费用最大流

先用满足下界,但是又有源汇,所以我们考虑将 2.2. 和 5.1. 结合起来。

大致就是用 5.1. 方式建边,然后对于 \(s,t\) 我们连一条 \(t\rightarrow s\) 的,容量为 \(+\infty\) 而费用为 \(0\) 的边。

然后直接跑最小费用最大流,得到烂摊子之后,再跑 \(s\)\(t\) 的最小费用最大流,有点像把问题 贰、叁、5.1 全部结合起来的味道。

5.3.有源汇可行最小费用流

先满足每条边的下界,用 5.2. 的方法,对于 \(s,t\) 我们连一条 \(t\rightarrow s\) 的,容量为 \(+\infty\) 而费用为 \(0\) 的边,然后跑从 \(ss\rightarrow tt\) 的最小费用最大流满足下界,然后对于烂摊子跑从 \(s\rightarrow t\) 的最小费用流。

为什么后面还要跑最小费用流?因为有可能从 \(s\rightarrow t\) 的流有可能是负的花费,至于这个负的花费,因为我们跑费用流会激活一些负权边。

5.4.有源汇可行最小费用最小流

先用 5.3. 跑出一个可行最小费用流,然后从 \(t\rightarrow s\) 跑反图,跑最小费用最大流。

陆、有负权费用流

它已经没有 "可行" 二字啦(每条边没有上下界了)!但是思路有相似性。

先考虑没有源汇点的情况。

负环当然是好东西,它可以让你的费用变小,所以我们有一种想法 —— 一个一个把所有负环都找出来,然后加到答案里面去。找环已经很困难了,我们还要一个一个找,这个算法肉眼可见的 \(\mathcal O(\tt{TLE})\).

能否由贪心入手?贪心地选择每个负权边并把他们流满,但是作为流它可能不合法,这个时候我们就需要调整,将其调整为合法的流,而说到调整,有没有想到 1.2. 里面的东西:

而这条边剩下的一些容量 \(c-low\),就放在网络里面自行调整

思路相似由此可见,但是亦有差异:

处理可行流,我们强制流满(下界),并且不可反悔。

而有负权环,我们一开始流满(上界),但是可以 "退款"。

那么我们怎么实现退款?这里,\(\text{NOI Ag}\) 的学长提出了他的方法:

根据斜对称性,一条边的流的减少等价于它反向边的流的增加。

也就是说,对于一条边 \(\lang u,v,w,c\rang (w<0)\),它反向边的容量就是它 "可退款" 的数量,而既然我们要实现可以退全款,就让它和它的反边初始容量都为 \(c\) 就可以了。

由于我们是将所有负流的贡献全部加起来,得到一个负边流满的 \(ans\),即

\[ans=\sum_{e\in E,w_e<0}w_e\times c_e \]

然后我们加上调整所不得不选上的正权边,对于一条边 \(\lang u,v,k,c\rang (k<0)\),考虑这样建图

graph LR subgraph 6. ss((ss)) tt((tt)) u((u)) v((v)) ss-->|w=0/c|v v-->|w=-k/c|u u-->|w=0/c|tt end

然后跑最小费用最大流,得到 \(cost\),最后的答案就是 \(cost+ans\).

如果有源汇点?嘿,往 \(t\rightarrow s\) 连一条容量 \(+\infty\) 边权为 \(0\) 的边,这难道不就转化成无源汇的问题了吗?

柒、总结

这些东西排列组合,可以把人搞晕......

但是本质上都是差不多的,对于只有上下界的情况,我们直接使用 壹、贰 。

对于又有上下界又有费用要求,首先我们需要的肯定是满足下界,所以先用 壹、贰 的方法(带上边权)跑最小费用最大流,然后再根据要求进行调整。

而负环这东西,使用 "正难则反" 的思路,转化为了先流满所有负边,然后调整负边成为合法流的 "无源汇可行流" 的情况。

posted @ 2021-02-06 12:18  Arextre  阅读(112)  评论(0编辑  收藏  举报