网络流 & 二分图小记
网络流的性质#
增广路定理#
加了反向边之后网络流可以以任意顺序增广,增广路不存在时一定为最大流。
最大流最小割定理#
网络的最大流等于最小 割。
从线性规划的角度看最大流与最小割互为对偶。
增量加边#
由于有增广路定理,在对网络流加边后,只要再跑一次网络流算法就能得到新的最大流。
退流删边#
删边比加边困难,如果不能转化为加边,可以通过退流删边。
假如要删 这条边,当前这条边流量为 ,则我们只需要让流入 的流量和流出 的流量减少 ,然后删除 。具体来说,从 到 跑一次最大流量为 的最大流,从 到 跑一次最大流量为 的最大流,然后将 和其反向边的边权置为 。
费用流的性质#
贪心增广#
每次走最短的增广路,当增广路不存在时必然为最小费用最大流。
凸性#
每次走一条增广路后新的增广路长度单调不降,因此费用是关于流量的凸函数。
消圈定理#
对于一个合法的最大流,不断找图中的负圈并且添加围绕负圈的流,当找不到负圈时流是最小费用最大流。
增量加边#
消圈本身效率极低,所以费用流算法一般不增量加边,但是模拟费用流或者通过费用流推导贪心算法时可以手动进行增量加边操作。
首先加边后我们先把新出现的增广路加入流,使得流最大,然后不断消除负圈,由消圈定理我们知道最后总能得到最小费用最大流。
效率优化:primal-dual 和 zkw#
使用类似 dinic 的 dfs,但是每次走最短的增广路,在某些图上会有较小的运行时间,但是时间复杂度较 EK 没有变化,仍然是伪多项式复杂度 。
注意到效率的瓶颈在于每次都需要跑一个 的最短路算法,参照 Johnson 算法,我们尝试给每个节点赋一个势能 ,并调整边 的边权为 ,使得边权非负,然后使用 Dijkstra 求最短路。
考虑初始时令势能为最短路,每轮增广后让势能加上当前的最短路,可以证明这样设置势能后边权非负。需注意势能可能会很大,小心 overflow。
w` = w + h[u] - h[v]
...
spfa(s, t);
while (dijkstra(s, t)) {
memcpy(cur, head, sizeof(cur));
maxflow += dfs(s, inf, t);
for (int i = 1; i < cnt; i++) h[i] += dis[i];
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?