zoukankan      html  css  js  c++  java
  • 网络流————最大流(学习笔记)(更新中)

    网络最大流

    一、 什么是网络最大流

    最大流
    如图,将点Vs定义为源点(起点),Vt定义为汇点(终点),每一条弧<u, v>代表从u 到v 的运输线,产品经这条弧由u 输送到v,弧旁的数字表示这条运输线的最大通过能力(以后简称容量,capacity)。

    其实,可以把这个图想成一个自来水的运输图,Vs是自来水厂,Vt想成是自己家,容量就是自来水管的长度。

    网络最大流,就是求在自己家放水是最大流量是多少。
    当然,在这个图上,就算自来水厂在怎么的放水,它最大出去的流量也只能有 4+8=12,自己在家在怎么的打开水龙头,最大流量也只能有 7+9=16.
    右图,就是一种可行的流量方法,简称可行流(滑稽)。

    二、一些基本概念

    1. 容量网络和网络最大流

    在这里插入图片描述
    容量网络(capacity network):设G(V, E)是一个有向网络,在V 中指定了一个顶点,称为源
    点(记为Vs),以及另一个顶点,称为汇点(记为Vt);对于每一条弧<u, v>∈E,对应有一个权值
    c(u, v)>0,称为弧的容量(capacity)。通常把这样的有向网络G 称为容量网络。(说白了就是带权的有向图)。

    弧的流量(flow rate):通过容量网络G 中每条弧<u, v>上的实际流量(简称流量),记为f(u, v)。(右图括号中右边的数),就是自来水管中正在流的水的流量。

    网络流(network flow):所有弧上流量的集合f = { f(u, v) },称为该容量网络G 的一个网络流。

    这里会有一些性质:

    1. 通过每弧的流量均不超过弧容量;
    2. 源点Vs 流出的总量为3 + 2 = 5,等于流入汇点Vt 的总量2 + 3 = 5;
    3. 对于除源点和汇点之外的中间顶点,它的流入总量等于流出总量。
      这些都很明显

    可行流(feasible flow):在容量网络G(V, E)中,满足以下条件的网络流f,称为可行流。

    1. 弧流量限制条件:0 ≤ f(u, v) ≤ c(u, v),<u, v>∈E (左图)
    2. 平衡条件:
      平衡条件

    上式中,f (u, v)表示从顶点u流出的流量, f(v, u)表示流入顶点u的流量, | f | 为该可行流的流量,即源点的净流出流量,或汇点的净流入流量。

    对于任何一个容量网络,可行流总是在存在的,如f = { 0 },即每条弧上的流量为0,该网络
    流称为零流(zero flow)。

    伪流(pseudoflow):如果一个网络流只满足弧流量限制条件(式6-1),不满足平衡条件,则
    这种网络流称为伪流,或称为容量可行流预流推进算法(求最大流的一种算法)时要用到。

    最大流(maximum flow):在容量网络G(V, E)中,满足弧流量限制条件和平衡条件、且具有
    最大流量的可行流,称为网络最大流,简称最大流。

    2. 链与增广路

    在容量网络G(V, E)中,设有一可行流f = { f(u, v) },根据每条弧上流量的多少、以及流量和
    容量的关系,可将弧分四种类型:

    1. 饱和弧, 即f(u, v) = c(u, v);
    2. 非饱和弧,即f(u, v) < c(u, v);
    3. 零流弧, 即f(u, v) =0;
    4. 非零流弧,即f(u, v) > 0。
      不难看出,饱和弧与非饱和弧,零流弧与非零流弧这两对概念是交错的,饱和弧一般也是非
      零流弧,零流弧一般也是非饱和弧。

    (chain):在容量网络中,称顶点序列(u, u1, u2, …, un, v)为一条链,要求相邻两个顶点之间
    有一条弧,如< u, u1>或< u1, u >为容量网络中一条弧。
    就是,不管方向,能到达的一条路径
    这样,在给定一个方向为正方向时,会有:

    1. 前向弧(方向与链的正方向一致的弧),其集合记为P+;
    2. 后向弧(方向与链的正方向相反的弧),其集合记为P–。
      链
      例如在图(a)中,指定的链为:P = { Vs , V1 , V2 , V4 , Vt },这条链在图(a)中用粗线标明。则
      P+和P–分别为:
      P+ = { <Vs , V1>, <V2 , V4>, <V4, Vt> },
      P– = { <V2, V1> }。
      注意,同一条弧可能在某条链中是前向弧,而在另外一条链中是后向弧。例如,如图(b)
      所示,弧<V2, V1>在链P1 = { Vs , V1 , V2 , V4 , Vt }是后向弧,而在链P2 = { Vs , V2 , V1 , V3 , Vt }是前向弧。这一点在求最小费用最大流时要用到。

    增广路(augmenting path):
    设f 是一个容量网络G 中的一个可行流,P 是从Vs 到Vt 的一条链,若P 满足下列条件:

    1. 在P 的所有前向弧<u, v>上,0 ≤ f(u, v) < c(u, v),即P+中每一条弧都是非饱和弧;
    2. 在P 的所有后向弧<u, v>上,0 < f(u, v) ≤ c(u, v),即P–中每一条弧是非零流弧。
      则称P 为关于可行流f 的一条增广路,简称为增广路(或称为增广链可改进路)。

    沿着增广路改进可行流的操作称为增广(augmenting)。
    下面具体地给出一种方法,利用这种方法就可以把f 改进成一个值更大的流f1。这种方法是:

    1. 不属于增广路P 的弧<u, v>上的流量一概不变,即f1(u, v) = f(u, v);
    2. 增广路P 上的所有弧<u, v>上的流量按下述规则变化:(始终满足可行流的2 个条件)
      a) 在前向弧<u, v>上,f1(u, v) = f(u, v) +α;
      b) 在后向弧<u, v>上,f1(u, v) = f(u, v) -α。

    称α为可改进量,它应该按照下述原则确定:
    i) α既要取得尽量大;
    ii) 又要使变化后f1 仍满足可行流的两个条件 - 容量限制条件和平衡条件。

    在下图中,粗线为一条增广路,可知 α 为2,增广之后变成右图。此时可行流由5 变成 7;

    增广路
    说一下我的理解,当增广路中,全是前向弧时,很容易理解。
    当有后向弧时,就是上图描述的情况,在点V1进来的水变成全部来自点Vs,而原本由V2流向V1的水,改为流向V4。(神奇)

    3. 残留容量与残留网络

    残留网络
    在上图给点的容量网络G(V, E)及可行流f,中:
    残留容量(residual capacity):就是自来水管中没用完空着的流量空间。上图,在点Vs和V2之间,
    残留容量就是 4-3=1.

    残留网络,就是上面的图(b)的样式。
    重点:会发现,在图(b)残留网络中去找一条源点到汇点的增广路,如( Vs, V2, V4, Vt ),这里走的是值为1, 4, 2。在图(a)中沿路径增广1个单位的流量,然后在根据增广后的图(a),再构造残留网络,再增广,再构造残留网络,再增广…
    你就会发现,不能再找到增广路,这时,最大流就求出来了。

    4. 割与最小割

    (cut):在容量网络G(V, E)中,设E’⊆E,如果在G 的基图中删去E’后不再连通,则称E’是G 的割。割将G 的顶点集V 划分成两个子集S 和T = V - S。将割记为(S, T)。

    s-t 割:更进一步,如果割所划分的两个顶点子集满足源点Vs∈S,汇点Vt∈T,则称该割为s-t 割。s-t 割(S, T)中的弧<u, v>(u∈S, v∈T)称为割的前向弧,弧<u, v>( u∈T, v∈S)称为割的反向弧。(这里只讨论s-t割)。

    割的容量:设(S, T)为容量网络G(V, E)的一个割,其容量定义为所有前向弧的容量总和,用c(S,
    T)表示。即:c(S, T)=Σc(u, v) u∈S,v∈T,<u, v>∈E。
    注意:在统计割的容量时,不统计反向弧的容量。

    最小割(minimum cut):容量网络G(V, E)的最小割是指容量最小的割。

    割的净流量。设f 是容量网络G(V, E)的一个可行流,(S, T)是G 的一个割,定义割的净流量f(S,
    T)为:f(S, T)=Σf(u, v) u∈S,v∈T,<u, v>∈E 或<v, u>∈E。
    注意:在统计割的净流量时,反向弧的流量为负值,即如果<v, u>∈E,那么在统
    计割的净流量时f(u, v)是一个负值。

    割
    在上图中,
    S = { Vs, V1 },则T = { V2, V3, V4, Vt }。
    割(S, T)的容量 c(S, T) 为:c(S, T) = Cs2 + C14 + C13 = 4 + 2 + 2 = 8。
    割(S, T)的净流量为:f(S, T) = fs2 + f21 + f14 + f13 = 3 + (-2) + 2 + 2 = 5。

    定理(网络流流量与割的净流量之间的关系)::网络流的流量等于任何割的净流量。
    定理(网络流流量与割的容量之间的关系):网络流的流量小于或等于任何割的容量。

    三、最大流最小割定理

    定理(增广路定理) 设容量网络G(V, E)的一个可行流为f,f 为最大流的充要条件是在
    容量网络中不存在增广路。
    定理(最大流最小割定理) 对容量网络G(V, E),其最大流的流量等于最小割的容量。

    根据上面两个定理,可以总结出以下4 个命题是等价的(设容量网络G(V, E)的一个可行流
    为f):
    (1) f 是容量网络G 的最大流;
    (2) | f |等于容量网络最小割的容量;
    (3) 容量网络中不存在增广路;
    (4) 残留网络G’中不存在从源点到汇点的路径。
    最大流最小割
    例如,图(a)所示的网络流是容量网络中的最大流,其流量为8。粗线所表示的弧组成了一个最小割,其容量也为8。在图(a)中,不存在增广路,而在图(b)所示的残留网络中,也不存在从源点到汇点的路径。

    四、网络最大流的求解

    网络最大流的求解主要有两大类算法:增广路算法(augmenting path algorithm)和预流推进算法(preflow-push algorithm)

    1. 增广路算法

    根据增广路定理,为了得到最大流,可以从任何一个可行流开始,沿着增广路对网络流进行增广,直到网络中不存在增广路为止,这样的算法称为增广路算法。问题的关键在于如何有效地找到增广路,并保证算法在有限次增广后一定终止。
    增广路算法的基本流程是:
    (1) 取一个可行流f 作为初始流(如果没有给定初始流,则取零流f= { 0 }作为初始流);
    (2) 寻找关于f 的增广路P,如果找到,则沿着这条增广路P 将f 改进成一个更大的流;
    (3) 重复第(2)步直到f 不存在增广路为止。
    增广路算法的关键是寻找增广路和改进网络流
    流程图:
    流程图

    2. 预流推进算法

    预流推进算法是从一个预流出发对活跃顶点沿着允许弧进行流量增广,每次增广称为一次推进(push)。在推进过程中,流一定满足流量限制条件,但一般不满足流量平衡条件,因此只是一个伪流。此外,如果一个伪流中,从每个顶点(除源点Vs、汇点Vt 外)流出的流量之和总是小于等于流入该顶点的流量之和,称这样的伪流为预流(preflow)。因此这类算法被称为预流推进算法。

    五、 一般增广路方法–Ford-Fulkerson 算法

    百度百科:Ford-Fulkerson算法(FFA)是一种贪婪算法,用于计算流网络中的最大流量。 它被称为“方法”而不是“算法”,因为在残差图中找到增广路径的方法没有完全指定,或者在具有不同运行时间的若干实现中指定。 它由L. R. Ford,Jr。和D. R. Fulkerson于1956年出版。 名称“Ford-Fulkerson”通常也用于Edmonds-Karp算法,该算法是Ford-Fulkerson方法的完全定义的实现。
    在Ford-Fulkerson 算法中,寻找增广路和改进网络流的方法是标号法(label method),接下来先看标号法的两个实例,再介绍标号法的运算过程和程序实现。

    1. 标号法实例

    以下两个实例分别从初始流为零流和非零流出发采用标号法求网络最大流。

    (1) 标号法求最大流的实例1 - 初始流为零流。

    过程

    (2) 标号法求最大流的实例2 - 初始流为非零流。

    过程
    具体的文字描述,照着图片推一遍,挺有意思的。

    最短增广路算法

    最短增广路算法思想:

    每次在层次网络中找一条含弧数最少的增广路进行增广。

    具体步骤:
    1. 初始化容量网络和网络流;
    2. 构造残留网络和层次网络,若汇点不在层次网络中,则算法结束;
    3. 在层次网络中不断用BFS 增广,直到层次网络中没有增广路为止;每次增广完毕,在层
      次网络中要去掉因改进流量而导致饱和的弧;
    4. 转步骤(2)。
    看图模拟

    在这里插入图片描述
    到这里,相信想法是有了的





    Edmonds-Karp算法

    模板链接



    连续最短增广路算法–Dinic 算法

    算法思想

    Dinic 算法的思想也是分阶段地在层次网络中增广。它与最短增广路算法不同之处是:最短增广路算法每个阶段执行完一次BFS 增广后,要重新启动BFS 从源点Vs 开始寻找另一条增广路;而在Dinic 算法中,只需一次DFS 过程就可以实现多次增广,这是Dinic 算法的巧妙之处。
    Dinic算法的具体步骤为:

    1. 初始化容量网络和网络流;
    2. 构造残留网络和层次网络,若汇点不在层次网络中,则算法结束;
    3. 在层次网络中用一次DFS 过程进行增广,DFS 执行完毕,该阶段的增广也执行完毕;
    4. 转步骤(2)。
    看图模拟

    Dinic

    Dinic 模板

    模板链接

    练习题目:
    POJ 1149
    POJ 1273(模板题)

  • 相关阅读:
    iOS7's subview trimmed if out of parent view bounds
    iOS 7 — navigationController is setting the contentInset and ContentOffset of my UIScrollView
    友盟统计-页面访问路径
    iOS-Get the NSString height in iOS 7
    php
    How to Install Laravel PHP Framework on CentOS 7 / Ubuntu 15.04
    apache-.htaccess
    ios-member center
    lamp
    mysql
  • 原文地址:https://www.cnblogs.com/jizhihong/p/13337360.html
Copyright © 2011-2022 走看看