网络流学习总结
网络流总结
算法
网络流
设 定义在二元组 上的实数函数且满足
- 容量限制:对于每条边,流经该边的流量不得超过该边的容量,即\(f(u,v) \le c(u,v)\)
- 斜对称性:每条边的流量与其相反边的流量之和为 0,即 \(f(u,v) = -f(v,u)\)
- 流守恒性:从源点流出的流量等于汇点流入的流量
最大流
我们有一张图,要求从源点流向汇点的最大流量(可以有很多条路到达汇点),就是我们的最大流问题。
最小费用最大流
最小费用最大流问题是这样的:每条边都有一个费用,代表单位流量流过这条边的开销。我们要在求出最大流的同时,要求花费的费用最小。
最小割
割其实就是删边的意思,当然最小割就是割掉 \(X\) 条边来让 \(S\) 跟 \(T\) 不互通。我们要求 \(X\)条边加起来的流量综合最小。这就是最小割问题。
实现
Dinic 算法 的过程是这样的:每次增广前,我们先用 BFS 来将图分层。设源点的层数为 ,那么一个点的层数便是它离源点的最近距离。
通过分层,我们可以干两件事情:
- 如果不存在到汇点的增广路(即汇点的层数不存在),我们即可停止增广。
- 确保我们找到的增广路是最短的。(原因见下文)
接下来是 DFS 找增广路的过程。
我们每次找增广路的时候,都只找比当前点层数多 的点进行增广(这样就可以确保我们找到的增广路是最短的)。
Dinic 算法有两个优化:
- 多路增广 :每次找到一条增广路的时候,如果残余流量没有用完怎么办呢?我们可以利用残余部分流量,再找出一条增广路。这样就可以在一次 DFS 中找出多条增广路,大大提高了算法的效率。
- 当前弧优化 :如果一条边已经被增广过,那么它就没有可能被增广第二次。那么,我们下一次进行增广的时候,就可以不必再走那些已经被增广过的边。
最小费用最大流
网络流图中,花费最小的最大流被称为 最小费用最大流 ,这也是接下来我们要研究的对象。
类似Dinic算法
我们可以在 Dinic 算法的基础上进行改进,把 BFS 求分层图改为用 SPFA(由于有负权边,所以不能直接用 Dijkstra)来求一条单位费用之和最小的路径,也就是把 \(w(u,v)\) 当做边权然后在残量网络上求最短路,当然在 DFS 中也要略作修改。这样就可以求得网络流图的 最小费用最大流 了。
对于一条边 \((u,v,w,c)\)(其中 \(w\) 和 \(c\) 分别为容量和费用),我们建立正向边 (u,v,w,c)和反向边 \((v,u,0,-c)\)(其中 \(-c\) 是使得从反向边经过时退回原来的费用)。
上下界网络流
上下界网络流本质是给流量网络的每一条边设置了流量上界 \(c(u,v)\) 和流量下界 \(b(u,v)\) 。也就是说,一种可行的流必须满足 \(b(u,v) \le f(u,v) \le c(u,v)\) 。同时必须满足除了源点和汇点之外的其余点流量平衡。
最大权闭合子图
闭合子图:
- 它是一种子图
- 它还是有向图的子图
- 它还可以一路走到底
- 对于每个点,从它出发,能够走到的所有点都属于闭合子图中
最大权闭合子图就是原图中点权和最大的闭合子图。
实现
最大权闭合子图问题可以使用最小割解决
连边方式
-
对于所有原图中的边$ (u, v)$ ,连边 \(u \rightarrow v\),容量为 \(\inf\) 。
-
对于每个原图中的点 \(u\) ,设 \(u\) 的权值为 \(val[u]\) :
- 若 \(val[u] > 0\)(正权点),连边 \(S \rightarrow u\) ,容量为 \(val[u]\)。
- 若 $val[u] < 0 $(负权点),连边 \(u \rightarrow T\) ,容量为 \(-val[u]\)。
至于 \(val[u] = 0\)(零权点)的情况,向 \(S\) 还是 \(T\)连边对答案并没有影响。
直接跑最小割,最大权 = 正点权和 - 最小割,而最大权闭合子图的节点就是与 \(S\) 联通的部分。
技巧
拆点
对于一个有点权的点来说,拆点就是把一个点拆开为多个,这样可以方便把点权变成边权,满足题目的一些要求。
缩点
对于一些题来说,如果直接加点建边很有可能因为边和点过多而挂掉,此时就需要按照题意来进行建边上的优化。