网络流学习笔记
啊啊是的,又来学网络流了。
网络
设有一张有向图
在这之中有两个特殊的点:源点
流
设定义域在二元组
- 容量限制:对于每条边,都有
。 - 斜对称性:对于每条边,都有
。 - 流守恒性:从源点流出的流量
汇点流入的流量,即:
我们就称
这里再给一个酷炫的定义:
最大流
对于网络
下面将讲几个求解最大流的算法:
Ford-Fulkerson 增广类
首先捋清楚一些定义:
定义残量网络
定义增广路为在残量网络
定义增广操作为给某一增广路的每一条边
对此,我们可以发现:
最大流的求解就可以视为若干次增广操作分别得到的流的叠加。
不过,这里有一点需要注意,根据流函数的斜对称性,我们需要有一个「退流」操作,即若我们对于
「退流」操作实际上是产生了一个「抵消」的操作,为的是能够保证我们可以自由的原则增广增广路的顺序(即给我们一个反悔的机会)。
我们可以发现,只要
证明?证明如下(PS:真的好想要一个和 OI-Wiki 一样的 Markdown 书写方案啊):
考虑每一次我们增广都相当于从残留网络中拿掉一条边再换上一条反向边,当残量网络中的
和 不连通的时候自然我们换掉的边集是一组割边,然后根据最大流最小割定理易得我们此时得到的就是最大流。
根据上述定义,我们不难有如下一种算法,设算法开始时我们的残留网络
- 从
出发进行 直到点 。 - 将最先到达点
的路径流上路径 上的最小容量,即 ,然后给 增加流量 ,给反向边退流 ,最大流增加 ,并得到新的残量网络 。 - 对
重复进行操作,直到我们的 无法从 到达点 。
这也就是我们的 Edmonds-Karp 算法,时间复杂度
下面我们再补充定义几个东西:
设有网络
更加形式化的,我们称
定义阻塞流
这个时候我们有如下算法:
- 在
上 出层次图 。 - 在
上 出阻塞流 。 - 将
并入原先的最大流流中,即 , - 重复上述过程,直到
上不存在 到 的路径。
这个算法就是大名鼎鼎的
然后就是当前弧优化,就是在
为了避免这样的缺陷,我们对每个节点维护出边表中第一条还有必要尝试的出边,我们称这个指针为「当前弧」,称这样的做法为「当前弧优化」,这样才能保证
时间复杂度
Push-Relabel 预流推进类
预流推进的核心思想是通过对单个节点进行更新,直到没有节点需要更新来求解最大流。
首先必然是引入一些相关定义:
定义超额流
若
预流推进算法维护每个节点的高度
我们设残量网络
则称函数 为残量网络 的高度函数。
设
上的高度函数为 ,对于任意两个节点 ,如果 ,则 不是 上的边。
Tips: 准确的说,预流推进实际上维护了映射
算法只会在
而如果对于溢出的节点
于是,我们希望尽可能的将超额流从
如果
而如果对于溢出的节点 relabel
操作,则需要满足以下条件:
重贴标签时,将
对于初始化操作,我们需要完成:
上述将
然后我们考虑每一次选节点的时候,都优先选择高度最高的那个溢出的节点,于是不难有算法:
- 初始化;
- 选择溢出节点中高度最高的节点
,并对它所有可以推送边进行推送; - 如果
仍溢出,对它重贴标签,回到步骤 ; - 如果没有溢出的节点,则算法结束。
这也就是我们的欢乐皮皮 HLPP 算法,复杂度为
下面是对 HLPP 的两个优化:
HLPP 使用的时候卡上界卡的比较紧;我们可以在初始化高度的时候进行优化,具体的说,我们初始化
在
GAP 优化
HLPP 的推送条件是
最小割
根据最大流最小割定理,我们可以知道最小割的代价就是最大流。
然后我们可以用最大流做最小割的问题了。
建模原则
如果有一些东西我们渴望捆绑起来,则将描述他们之间关系的边设为
剩下的……因题目而异吧……
集合划分模型
一般来处理这样的问题:
设有集合
和 ,每个物品都有两个属性 和 ,表示放入集合 时会有 的代价,放入集合 时会有 的代价,还有 个捆绑关系,即如果 和 没有分在同一个集合内,则产生 的代价。
我们考虑将源点
费用提前计算
一般用来处理某个人在处理第
我们考虑这个人可以隐分身,然后就按照正常的方式去建图就好了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)