解决的是一个类似于管道输送的问题。
假设现在有一个管道网络,一共有
求解网络最大流比较常用的算法是 Dinic,此外网络流常常利用建模思想来解决一些看似不好入手的题。看似不是图论的题
最大流算法
梦开始的地方:Ford-Fulkerson
FF 算法是增广路网络流算法的起源。
什么是增广路
简单来说,就是还能流的路径。
具体的,我们为一个网络建立残量网络,原图中的边保持不变,而对于每条边都有一个对应的反向边,初始容量为
在 FF 算法中,每轮增广时会从
不难发现反向边的作用在于给算法一个反悔的机会:流过去之后还可以“反悔”,再流回来,这两种过程是等效的,但是避免了算法每一步都要最优化。
不难发现一次增广至少会流
当边权巨大的时候就寄了,所以需要一个不依赖于边权的算法。
EK 算法:多项式算法
上面的 FF 算法中可能会陷入一个反悔的困境,导致其时间复杂度非常大。因此 EK 算法利用 bfs 代替 dfs,来寻找可行的增广路。
EK 算法在当前残量网络上利用 bfs 来为节点按照深度编号并且找到最短的增广路。然后再利用这条增广路来更新答案。
为什么寻找最短的路呢?目的就是防止不断跳横叉边反悔卡住。在走最短路时,相同深度节点之间的路并没有起到向汇点流动的作用,可以先不用流。
注意 EK 算法中标号会不断变化。因此横叉边也不是不可能没有流量。
这个算法时间复杂度是多少呢?一次 bfs 会寻找到一条增广路,而 bfs 的时间复杂度显然是
Dinic 算法:竞赛不卡
竞赛网络流会卡 FF、EK,但是不卡 Dinic,因为 Dinic 的时间复杂度是
Dinic 算法相较于 EK 算法做了一个改进就是一轮编号之后利用 dfs 进行多路增广。
但是这样会被一些数据 hack 掉,比如:
其中
为了避免这样的情况,我们维护一个当前弧指针
优化后的时间复杂度就很优秀了,为
最小割
定义一个割为将原图点集
之值。最小割就是使
什么?最大流就等于最小割?证明
费用流
现在一个弧不仅有流量限制,还有单位花费,在弧
做法也很简单,利用 EK 算法或者 Dinic 算法,只不过将 bfs 中深度改为从源点的最短路(边权是
常见模型
说实话模型才是网络流的核心
二分图匹配
我们考虑到一个左部点只能和一个右部点相匹配,可以看成一个左部点只能流出
因此我们建立超级源汇点
事实上,Dinic 算法在二分图上的效率十分优秀,为
二选一
有
个物品和两个集合 。如果你将第 个物品放入 集合你会花费 的代价;放入 中会花费 的代价,不能不放。同时还有 条限制,每条限制形如 ,表示如果 不在同一个集合就要花费额外的 。求最小花费。
经典的最小割题目。我们建立超级源汇
最大权闭合子图
给定一张有向图,每个点都有一个权值(可以为正或负或
),你需要选择一个权值和最大的子图,使得子图中每个点的后继都在子图中。
此题的建模十分巧妙,方法如下:
建立超级源汇
我们考虑一个图:
那么这个图的生成网络就是这样子的:
首先我们证明一下得到的答案是合法的,即这个构造是闭合子图:
显然不割掉一条源点流出的边就会让
其次我们来看这个是否为最优的:
注意到我们的最小割