流网络的三个性质
容量限制:对所有的u,v∈v,f(u,v)<=c(u,v)
反对称性:f(u,v)= -f(v,u)
流守恒性:对于所有的u∈v-{s,t} ,v∈v, ∑f(u,v)=0;
残留网络
残留网络本身也是一个网络流,由可以容纳更多网络流的边组成。
残留容量Cf(u,v)=c(u,v)-f(u,v)
C(u,v)为正,f(u,v)可正,可负。f(u,v)为正是表示的是正向边,边(u,v)在残留网络中;f(u,v)表示的是反向边,(v,u)在残留网络中。
Ford-fulkkerson算法
FORD-FULKERSON(G, s, t)
1 for each edge (u, v) ∈ E[G]
2 do f[u, v] ← 0
3 f[v, u] ← 0
4 while there exists a path p from s to t in the residual network Gf
5 do cf(p) ← min {cf(u, v) : (u, v) is in p}
6 for each edge (u, v) in p
7 do f[u, v] ← f[u, v] + cf(p)
8 f[v, u] ← -f[u, v]
时间复杂度为O(Ef)
Ek算法
用广度优先算法来搜索残留网络。伪代码如下:
int bfs()
queue Q
push source to Q
mark source as visited
keep an array from with the semnification: from[x] is the
previous vertex visited in the shortest path from the source to x;
initialize from with -1 (or any other sentinel value)
while Q is not empty
where = pop from Q
for each vertex next adjacent to where
//这里要改为所有的点,并不是邻接的点,因为流量可以消掉的,
//假设边(u,v)在G中,可以反向流。
if next is not visited and capacity[where][next] > 0
push next to Q
mark next as visited
from[next] = where
if next = sink
exit while loop
end for
end while
// we compute the path capacity
where = sink, path_cap = infinity
while from[where] > -1
prev = from[where] // the previous vertex
path_cap = min(path_cap, capacity[prev][where])
where = prev
end while
// we update the residual network; if no path is found the while
loop will not be entered
where = sink
while from[where] > -1
prev = from[where]
capacity[prev][where] -= path_capacity
capacity[where][prev] += path_capacity
where = prev
end while
// if no path is found, path_cap is infinity
if path_cap = infinity
return 0
else return path_cap
上面的伪代码有一点小问题,那就是在搜索where的边时,要搜索所有的边。只要残留容量大于0,就ok了。
参考:算法导论
http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=maxFlow