网络最大流
众所周知,网络流是图论的一个很重要的内容,也很有难度(主要难在建模)。
网络流的基础概念这里提一下:
容量网络:设G(V,E),是一个有向网络,在V中指定了一个顶点,称为源点(记为Vs),以及另一个顶点,称为汇点(记为Vt);对于每一条弧<u,v>属于E,对应有一个权值c(u,v)>0,称为弧的容量.通常吧这样的有向网络G称为容量网络.
这里主要讲一下网络流最简单的一个分支:网络最大流。
什么是网络最大流?
通俗的说,如果把网络流比作水流,源点比作水龙头,汇点比作农田,边表示水管,那么,网络最大流表示的就是水龙头放水经过自来水管能够灌溉农田的最大水量。路途中其流量必然不能超过管的容积(否则管就爆了)。
下面给出一张图理解(字有点丑,不要介意):
s为源点,t为汇点,
如图,有s->a->c->t,经过容量为1,7,2的边,路径最大流为1(路径中最小的边)。
s->c->t,经过容量为4, 2的边,但容量为2的边剩余容量为0,所以流为1,
s->b->c->t,经过容量为6,2,2的边,路径c->t中已经没有容量剩余,所以流为0,
s->b->e->t,经过容量为6,1,4的边,路径b->e中流最大为1,所以流为1.
所以,这张图的网络最大流为1+1+0+1 = 3.
怎么求网络最大流?
由定义,非常自然的,我们可以求出源点到汇点每条路径中水管容积最小的管的容积(水量不能超过每一条管的容积),累加这些路径的答案。
当图中不再存在增广路(即每一条路径中有一条边内没有容量剩余)时,就求出了网络最大流。
由此,我们推出了EK(Edmonds-Karp)算法。
EK算法
基于刚才的分析,我们可以通过BFS不断寻找增广路,直至图中不存在增广路为止。
在每轮寻找增广路的过程中,EK算法只考虑图中所有f(x, y) < c(x, y)的边,用BFS找到任意一条从S到T的路径,同时计算出路径上剩余容量的最小值minf, 则网络的流量可以增加minf。
具体实现步骤如下:
(1) BFS寻找增广路,若能找到,转步骤(2).否则转步骤(3)
(2) 更新剩余容量,将流累加.
(3) 输出累加的流,即为最大流。
代码如下:
1 #include<bits/stdc++.h>
2 #define ll long long
3
4 using namespace std;
5
6 const int inf = 1 << 29, N = 1000010;
7
8 int head[N], cnt = 1;
9 int n, m, s, t, maxflow = 0;
10 struct node{ int to, next,v;} e[N];
11
12 void add(int x, int y, int z){