首页 > 代码库 > 网络流算法Push-relabel的Python实现
网络流算法Push-relabel的Python实现
网络流的背景我就不多说了,就是在一个有向图中找出最大的流量,有意思的是,该问题的对偶问题为最小割,找到一种切分,使得图的两边的流通量最小,而且通常对偶问题是原问题的一个下界,但最小割正好等于最大流,即切割的边就是最大流中各个path饱和边的一个组合。说得可能比较含糊,这里想要了解清楚还是查阅相关资料吧。
最大流最原始最经典的解法就是FF算法,算法复杂度为O(mC),C为边的容量的总和,m为边数。而今天讲的Push-relabel算法是90年代提出的高效算法,复杂度为O(n^3),其实网络流最关键的步骤就是添加反向边,得出剩余图。而其他的改进就是为了在寻找增广路径时尽可能贪心,流量尽可能大。
好了,开始讲Push-relabel的主要思想,首先构造一个函数excess,代表每个节点保存的流量,就是等于该节点的入流量-出流量,正常来说,s的保存流量为负,t的保存流量为正,其他节点的保存流量均为0,而算法的最终目标就是这个,此外还定义一个height函数(h),表示每个节点的高度。然后,初始化过程是,h(s)=n,h(v)=0,对于所有不为s的节点,f(s, u)=c(s, u),对于所有从s出发的边都默认饱和,这是上界。接着,就是Push-relabel的过程了,首先遍历图中所有节点,如果存在非t的且excess大于0的节点v,则查看v出发的所有边(v, w),如果h(v)>h(w),则可以将label,即excess的流量,传递给w,如果该边为正向边,传的大小为bottleneck=min{excess(v), c(v,w) - f(v, w)},否则bottleneck=min{excess(v), f(v, w)},传完之后,继续寻找excess大于0的节点,注意,如果v有边,但所有边都是h(v)<h(w),则将v的高度提升1,继续寻找。
源代码如下:
注意图的输入格式需满足DIMACS格式。
__author__ = 'xanxus' nodeNum, edgeNum = 0, 0 arcs = [] class Arc(object): def __init__(self): self.src = http://www.mamicode.com/-1>
希望对大家有所帮助。网络流算法Push-relabel的Python实现