网络流
网络流
定义
用水管来类比:
自来水厂(源点)要经过水管(边)把水运到石老板家(汇点)
每条单向水管连接两个站点,水管都有一个最大流量,源点有无限的水。显然,每条水管可能有水流,可能没有
问:自来水厂最多能给石老板送多少水
重点概念:
- 网络:图(一般为有向无重边)
- 容量网络:边权为该边容量的网络
- 流量网络:边权为该边实际流量的网络
- 剩余网络:容量网络边权减去剩余网络对应边权形成的网络
- 满流:流量网络的流量达到最大(即流入汇点的流量最大)
- 增广路:剩余网络中从源到汇使路径中最小剩余边权不为零的路径
- 超级源 & 超级汇:有多个源点与汇点时,建立一个超级源和一个超级汇,连向源点和汇点。
性质:
- 剩余网络在满流时不会有一条增广路
若满流时剩余网络仍有增广路,则沿着增广路增加流量总能使最终流量增加
- 任何一个合法的流量网络中,除了源和汇外的所有节点,入度都等于出度
水不会在中间节点凭空产生或消失
最大流最小割
给定一张图 $ G={V,E} $ 和源点 ,汇点 。
割集 $ C(S,T) $ 被定义为 $ {(u,v) |u\in S,v\in T,(u,v)\in E} $
即 为给定 两点集间的边集
最小割:边权和最小的割集 ,使 。
即花费最小代价把源点到汇点的所有路径切断,使源点汇点不连通,切断一条边的代价为它的边权。
举一个形象的例子:
某恐怖分母分子要花费最小代价切断若干条水管,使石老板家用不了自来水
可怜的石老板
性质:
- 一个流量网络的每一个割集,对应的流量和都等于总流量
一个形象的例子:恐怖分子切断了若干水管,使原来流向石老板家的水全部流走,最终从被切断水管流出的水量就是原来流向石老板家的水
- 同一张图上,每一个割都大于等于每一个流
考虑任意一个割集和任意一个流,由上一条性质得,割集对应的流量等于总流量,而割集对应的边权和大于等于边权对应流量(每一条边的流量小于等于边权)
- 最大流等于最小割
满流时,根据增广路的性质,剩余网络中源点汇点不存在最小剩余边权不为零的路径。断开所有剩余流量为零的边,另 为所有与源点连通的点集,,则割集 包含的所有边剩余流量为0,即流量等于容量。由此得 的边权和为最大流的流量。由上一条性质得, 为最小割。综上,最大流等于最小割。
求最大流
部分引自 OI-Wiki
这里仅介绍三种算法。
- Edmonds-Karp
- 预流推进
- 最高标号预流推进(最快)
Edmonds-Karp
每次 BFS
找到增广路,增广的同时把反向边边权增加即可。增广的时候要注意建造反向边,原因是这条路不一定是最优的,这样子程序可以进行反悔。假如我们对这条路进行增广了,那么其中的每一条边的反向边的流量就是它的流量。
预流推进
预流推进的核心在于允许节点的流入大于流出。我们把允许流入大于流出的网络称为预流。
预流推进算法维护每个结点的高度 ,并且规定溢出的结点 如果要推送超额流,只能向高度小于 的结点推送;如果 没有相邻的高度小于 的结点,就增加 的高度(重贴标签)。
初始化时,,并沿边推送起始节点流量。
最高标号预流推进
在预流推进法的基础上用数据结构维护高度最高的节点,即为最高标号预流推进(HLPP)
HLPP 还可进行如下优化:
-
将 初始化为 ,将 仍初始化为 。用 BFS 求出 ,即可减少大量重贴标签操作。
-
用桶代替优先队列,复杂度降低一个 。
-
因为每次取出的是最高节点,而重贴标签又只会增加当前节点高度,所以如果当前节点高度上没有其他节点,比当前节点高的所有节点都不可能向当前节点以后的节点推送流量,所以为了尽快将流量推送回 ,我们把所有比当前节点高的节点高度变为 。
优化后时间复杂度为
放上本人20分钟写完的HLPP
代码,部分参考 OI-Wiki 与 P4722 题解,因为本人巨喜欢空行,核心部分写了 65 行,一共 110 行。
1 |
|
应用
这题卡 Dinic…当然一般题目都不会卡它
建议参考 网络流24题
这里放上一道偏模板的题:U189165
考察了讲到的绝大部分知识
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!