网络流的SAP算法
来源:互联网 发布:wemall源码下载 编辑:程序博客网 时间:2024/05/18 02:24
网络流的最短增广路算法
在网络流问题中,最常见的方法是Ford-Fulkerson方法。这种方法每次找出一条残留网络中的增广路径并进行增广。整个算法运行过程满足流的三个性质(容量限制、反对称性、流守恒性)。与此相对的预流推进算法不满足流守恒性。在Ford-Fulkerson方法中,如何寻找增广路径是影响算法效率的主要因素。一种好的思想是每次寻找长度最短的路径。按照这种思想,如果采用BFS寻找增广路径,时间复杂度为O(n*m^2),效率不能令人满意。本文介绍一种最短增广路算法(Shortest Augmenting Path Algorithm),它的复杂度为O(n^2*m)。在实践中,这种算法效率还是比较高的。另外,著名的DINIC算法也与此算法有着密切联系。
在SAP算法中,我们定义每个顶点的距离标号(Distance Labels),即残留网络中这个点到汇点的距离。然后,我们只在距离标号相邻的点间寻找增广路径。如果从一个点出发没有容许边,就对重标记并回溯(类似预流推进)。首先介绍一些定义:
残留容量:容量-流量。即,残留容量r[i,j]=c[i,j]-f[i,j]。如果只求流值,则在网络流算法中只需记录残量,而不必记录容量和流量。
残留边、残留网络:有残留容量的边成为残留边,由网络的点集、残留边集构成残留网络。
距离标号 :对于每个点i,定义其在当前残留网络中到汇点的距离为d[i]。如d[t]=0。
容许边:当且仅当r[i,j]>0且d[i]=d[j]+1时,边(i,j)是容许边。我们的算法只考虑容许边。
算法的一开始,我们从汇点进行一次BFS求出距离标号。然后从源点开始递归操作。对于一个点i的操作,如果存在容许边(i,j),当j是汇点时增广并从源点开始递归,否则就令i是j的前驱,并递归j。否则对i重标号,使得d[i]=min{d[j]}+1 ( r[i,j] )>0,并回溯。当d[s]>=n时算法停止,此时不存在任何一条增广路。为提高效率可以改递归为迭代。可以参考一下《Network Flows: Theory, Algorithms, and Applications》中的伪代码:
01.
algorithm shortest augmenting path;
02.
begin
03.
x:=
0
;
04.
obtain the exact distance labels d(i);
05.
i:=s;
06.
while
d(s)<n
do
07.
begin
08.
if
i has an admissible arc
then
09.
begin
10.
advance(i);
11.
if
i=t
then
augment
and
set
i=s
12.
end
13.
else
retreat(i)
14.
end
;
15.
end
;
16.
17.
procedure
advance(i);
18.
begin
19.
let (i,j) be an admissible arc
in
A(i);
20.
pred(j):=i
and
i:=j;
21.
end
;
22.
23.
procedure
retreat(i);
24.
begin
25.
d(i):=min
{d(j)+1: (i,j)∈A(i) and r[i,j]>0}
;
26.
if
i<>s
then
i:=pred(i);
27.
end
;
28.
29.
procedure
augment;
30.
begin
31.
using the predecessor indices identify an augmenting path P from the source
to
the sink;
32.
δ:=min
{r[i,j] : (i,j)∈P}
33.
augment δ units
of
flow along path P;
34.
end
;
同样类似预流推进,我们有一个重要优化:间隙优化。即我们定义numb(k)是距离标号为k的点的个数。在重标记点i时,我们检查numb(d[i])。若numb(d[i])减为0,算法马上结束。我们很容易发现,点i被重标记则其距离标号必然小于n。而此时不存在此标号的顶点,则容许网络中必然不存在一条增广路径,因此算法结束。这个优化使得算法效率显著提高。
容易证明,SAP的复杂度为O(n^2*m)。而如果采用动态树,复杂度降为O(nmlogn)。只是动态树太过复杂。
提一下DINIC算法:
DINIC算法与SAP十分相似。只是,SAP只是开始进行一次BFS,每次只对单个顶点重标号。而DINIC不对单个顶点重标号,而是多次BFS计算标号。我们套用SAP算法并稍微修改:在过程retreat(i)中,不改变d[i],而是标记i为阻塞的。而容许边(i,j)的定义,其中j必须未阻塞。当源点阻塞,此时形成阻塞流,我们就进行一次反向BFS求得距离标号。由于每次BFS源点的距离标号单调递增,当它大于等于n时算法结束。
p.s.您可以无视本文,直接翻开《Network Flows: Theory, Algorithms, and Applications》(Ahuja, R.K.)
- 网络流的SAP算法
- 网络流最大流的sap()算法
- 网络流之SAP算法
- 网络流sap算法(whitecloud)
- 网络最大流SAP算法
- 网络流之sap算法
- hdu3549(网络流入门题-最大流的sap算法)
- 网络流之最大流sap算法
- 网络流最大流sap算法模板
- 网络流算法——SAP
- [转载]网络最大流SAP算法心得
- 网络流SAP算法(转)
- 网络流sap算法模板及分析
- ZOJ Flower (二分+网络流sap 算法)
- 网络流之SAP算法学习
- 网络流SAP+gap+弧优化算法
- 网络流之SAP算法学习
- 网络流 dinic算法 SAP 记录
- 很忙的一周
- ASP.NET - ListBox Web 服务器控件概述(上)
- g++ 3.4 版本occi
- 转:ADN Developer Days
- 黑链到底有没有用?
- 网络流的SAP算法
- OGC、WMS、WFS、WCS
- Recursively CopyDirectory(Source,Dest)
- ROLLUP和CUBE语句
- ASP.NET - ListBox Web 服务器控件概述(下)
- 雷军:为什么马云马化腾创业那么容易成功 自己却需要煎熬数年
- 《赢取竞争的100+N工具箱》
- Java Servlet Filter实现Web页面执行时间过滤器
- (转)免费经济学---为什么我喜欢互联网