网络流学习笔记
网络流(可看算法进阶)
感性的define : 一张DAG,有一个源点s,一个汇点t,其它每条边有一个容量c
从点u到点v的流量:不能让经过的点的流量超出该点的容量
增广路:还能继续流流量的路,也就是有一条路径,路径上的容量都不小于0
最大流:s到t的最大流量
求最大流算法的核心思路:不停地找增广路,流量加上该增广路上的最小容量,再更新增广路上的容量(路径上每个点都减去路径流量),直到没有增广路。
但但但是,上面的思路还有一个问题,就是该方法不能保证答案正确性,可能走了一条增广路后导致其它路径走不了,有可能不优。于是每条边e要加一条反边e',使得e和e'的容量之和为该边最开始的容量c。每次走边e时,流了x的流量,那么 \(e_c - x, e’_c + x\)。这样走反边相当于反悔操作,从而保证正确性(这句话可能有点抽象,建议画图)
接下来介绍几种求最大流的算法
- EK算法 复杂度 O(\(nm^2\))
思路:每次bfs找增广路来更新 - dinic算法 复杂度O(\(n^2m\))
思路:先bfs给图分层(标记深度),然后不停地dfs找增广路,但每次只走的dep[v] = dep[u] + 1的边,在该定义下的dfs找不到增广路后再重新bfs给图分层,直到图不连通(没有增广路了)。
优化:dfs走过的点不再走(当前弧优化),不走到汇点t没有流量的点(将dep[该点]赋值成0) - hlpp 复杂度 O(\(n^2\sqrt{m}\))
思路:我不会
补充:最大流算法复杂度很玄学,有时会跑地异常的快
最小割
定义:割掉一些边,使得s到t不连通,最小割就是割掉的这些边的容量c之和最小的割法
定理:最小割和最大流的值相等
感性证明:把最大流增广路中容量最小的点割一刀就是最小割(大概吧)
求最小割可以就用最大流的算法,反正值一样
费用流
定义:现在每条边不仅有容量c,还有花费w。要求走最大流的同时保证路径上的总花费(\(\sum_{每条走过的路径}\)路径的总费用w * 路径的流量f)最小
做法:将反边费用设为-w,找增广路时用spfa(这里用spfa是为了不走负环)。以EK为例,把bfs改成spfa,dinic应该也差不多。