问题定义
输入:一个有向图,起点s,终点t
目的:从起点输送更多的水去终点
一个简单的算法
augmenting path:起点到终点的简单路径
这个算法并不能保证找到最大流
先介绍一个最简单的算法,首先找到一条最短路径s->v1->v4->t,因为权值分别为4,4,3,故通过此路径的流量应为3,再将他们仨都减去3,那么v4-t就成了0,我们应该将这条边删除
继续找到下一条最短路径s->v1->v3->t,权值分别为1 ,2 ,3,故通过此路径的流量应为1,再将他们仨都减去1,那么s-v1就成了0,我们应该将这条边删除
接下来没有s到t的路径,结束,下右图就是多余的量
蓝色框的就是flow,流量
但是这种方法严重依赖于选取路径的顺序,显然,在本次选取的顺序中得到的结果并不是最大值5
如果更换一个选取路径的顺序,就可以求出正确答案
阻塞流
最大流也属于阻塞流
阻塞流就是没办法再继续输送更多的水
Ford-Fulkerson
算法:
创建一个residual图,初始化为原图
while(能找到一个简单路径){
在residual上找到一条简单路径
寻找这条简单路径中的最小权值minv
更新residual(resisual-=minv)
添加反向路径,这条路径上每条边的权值等于x
}
时间复杂度f*m(f是最大流长度,m是边的长度)
和简单算法一样,首先找一条最短路径
然后减去最小的权值
另外,添加一份反向边
继续找一条最短路径
添加一份反向边
继续找一条最短路径(如果没有反向边,其实就不会再有最短路径)
然后减去最小的权值
合并反向边,发现此时没有任何边到达t,应该终止程序
蓝色框为流过的流量
Edmonds-karps
是Ford-Fulkerson的特例,EK寻找路径的时候会遵循最短路优先(当作无权图)
算法:
创建一个residual图,初始化为原图
while(能找到一个简单路径){
在residual上找到一条最短路径(简单路径中的最短路径)
寻找这条简单路径中的最小权值minv
更新residual(resisual-=minv)
添加反向路径,这条路径上每条边的权值等于x
}
时间复杂度:m^2 *n(m是边的数目,n是顶点数目)
时间复杂度分析:每一轮循环都需要在m条边寻找最短路,residual图里最多是2m条边,找到最短路需要O(m)
最多循环m*n轮
最坏时间复杂度为m2*n
Dinic Algorithm
比Ek算法更快,时间复杂度是m*n2(m是边,n是顶点)
最多循环n-1轮 每一轮是mn
第一轮:
首先构造level graph
在level graph中寻找阻塞流,随便一个阻塞流即可(可以通过简单算法寻找)
PS:阻塞流不一定是最大流,最大流一定是阻塞流
更新residual