实现Push_Relabel 和 Edmonds-Karp 最大流算法
-
实现原理
-
Push_Relabel算法伪代码:
Push(v,e){
IF ?_? (?)≥?_? THEN
?=?_?; //饱和推送
ELSE
?=?_? (?); //非饱和推送
在边e上推送?单位的流;
更新剩余容量?_? ;
}
//**********************************
Initialize(){
?=?;
“反向BFS”设置高度值;
?(?)=?;
FOR ?∈?^+ (?) DO
在?(?,?)上饱和推送;
ENDFOR
}
//****************************
Push-Relable(G,s,t){
Initialize();
WHILE 存在盈余点 DO
选择最大高度盈余点v;
IF ∃?(?,?)满足?(?)=?(?)+?
THEN Push( v, e);
ELSE h(v)++; //Relabel
ENDWHILE
}
实现步骤
1.初始化:a.反向BFS算法对图上顶点高度进行初始化,即顶点高度初始化为到汇点的最小跳数;b.高度初始化完成后,将源节点高度设置为节点数;c.然后对源节点进行饱和推送;
2.只要存在盈余节点v,就选择最大高度盈余节点进行push_relabel
3.没有盈余节点后算法结束;
实现代码
from time import time
from queue import Queue
from heapq import heapify, heappop, heappush
from Network import Network
from queue import PriorityQueue
class PushRelabel(object):
__INF = 0xffffffff
def __init__(self, start, des, network):
self.__network = network # 原网络
self.__new_network = Network(network.get_node_num()) # bfs重构网络
self.__high = [0] * (network.get_node_num() + 1) # 高度函数
self.__start = start # 源点
self.__des = des # 汇点
self.__Re_flow = [0] * (network.get_node_num() + 1) # 盈余标记
self.__node_heap = [] # 最小堆,用于获取最大高度盈余节点
def __pre_flow(self): # 推送预流
self.__high[self.__start] = self.__new_network.get_node_num() # 初始化高度源点高度
for i in self.__new_network.all_neighbor(self.__start):
if self.__new_network.get_capacity(self.__start, i) > 0:
flow = self.__new_network.get_capacity(self.__start, i) # 饱和推送
self.__new_network.update_residual_capacity(self.__start, i, flow) # 更新边的剩余容量
self.__Re_flow[self.__start] -= flow # 更新盈余量
self.__Re_flow[i] += f