首页 > 代码库 > 第26章 最大流(正在修改)

第26章 最大流(正在修改)

一、综述

1.定义

定义1:流网络

定义2:残留容量

定义3:增广路径

已知一个网络流G=(V,E)和流f,增广路径p为残留网络G|f中从s到t的一条简单路径

能够沿一条增广路径p的每条边传输的网络流的最大量为p的残留容量,由下式定义:

c|f(p) = min{c|f(u,v) : (u,v)在p上}

定义4:割、净流、容量、最小割

净流和容量的区别:

穿过(S,T)的净流由双向的正网络流组成;在加上从S到T的正网络流的同时,减去从T到S的正网络流。

割(S,T)的容量仅由从S到T的连计算而得。从T到S的边在计算c(S,T)时是不算在内的。

2.性质

3.定理

定理1:

定理2:

定理3:

定理4:

定理5:

定理6:

对一个网络流G中任意流f来说,其值的上界面为G的任意割的容量

定理7:

二、代码

版本一:最大流,图用矩阵实现,求增广路径用BELLMAN-FORD实现

1.Mat_Flow.h
#include <iostream>using namespace std;#define NMAX 210class Mat_Flow{public:    int n;//点的个数。其中0是源点,1是汇点    int map[NMAX][NMAX];//网络费用    int net[NMAX][NMAX];//剩余网络    int path[NMAX];//增广路径,path[v]=u说明(u,v)在增广路径上    int ecost[NMAX];//源点到各点的最短路径    Mat_Flow(int num):n(num)    {        memset(map, 0, sizeof(map));    }    void AddSingleEdge(int start, int end, int value = http://www.mamicode.com/1)    {        map[start][end] = value;    }    void MakeGraph(int m);    bool bellman_ford();    int max_flow();};void Mat_Flow::MakeGraph(int m){    int start, end, value;    while(m--)    {        cin>>start>>end>>value;        AddSingleEdge(start, end, value);    }}bool Mat_Flow::bellman_ford(){    int i, j;    memset(path, -1, sizeof(path));    fill(ecost, ecost+NMAX, INT_MAX);    ecost[0] = 0;    bool flag = true;    while(flag)    {        flag = false;        for(i = 0; i <= n; i++)        {            if(ecost[i] == INT_MAX)                continue;            for(j = 0; j <= n; j++)            {                if(net[i][j] > 0 && ecost[i] + 1 < ecost[j])                {                    flag = true;                    ecost[j] = ecost[i] + 1;                    path[j] = i;                }            }        }    }    return ecost[n] != INT_MAX;}int Mat_Flow::max_flow(){    int i, j;    //初始时,剩余网络即为整个网络    for(i = 0; i <= n; i++)    {        for(j = 0; j <= n; j++)            net[i][j] = map[i][j];    }    int maxflow = 0;    //while there exists a path p from s to t int the residual network G1    //从剩余网络中找到一条增广路径,增广路径存在在path中    while(bellman_ford())    {        //do c|f(p) <- min {c|f(u,v):(u,v) is in p}        //计算增广路径上的净流        int v = n, cfp = INT_MAX, u;        while(v != 0)        {            //path存储的是增广路径,path[v]=u说明(u,v)在增广路径上            u = path[v];            cfp = min(cfp, net[u][v]);            v = u;        }        //更新最大流的大小        maxflow += cfp;        //更新剩余网络        //for each edge(u,v) in p        v = n;        while(v != 0)        {            u = path[v];            //f[u,v] <- f[u,v] + cfp            net[u][v] -= cfp;            net[v][u] += cfp;            //f[v,u] <- -f[u,v]            v = u;        }    }    return maxflow;}

2.main.cpp

#include "Mat_flow.h"/*5 100 1 160 2 131 3 121 2 102 1 43 2 92 4 143 5 204 3 74 5 4*/int main(){    int n, m;    while(cin>>n>>m)    {        Mat_Flow *G = new Mat_Flow(n);        G->MakeGraph(m);        cout<<G->max_flow()<<endl;        delete G;    }    return 0;}
3.测试数据

《算法导论》P405图26-5

4.运行结果

版本2:矩阵+HLPP(高度标号预流推进算法)

1."Mat_HLPP_Flow.h"

http://my.csdn.net/my/code/detail/50632

2.main.cpp
#include "Mat_HLPP_Flow.h"/*5 100 1 160 2 131 3 121 2 102 1 43 2 92 4 143 5 204 3 74 5 4*/int main(){    int n, m;    while(cin>>n>>m)    {        Mat_HLPP_Flow *G = new Mat_HLPP_Flow(n);        G->MakeGraph(m);        cout<<G->high_label_preflow_push()<<endl;        delete G;    }    return 0;}
3.测试数据与测试结果

同上

三、练习

26.1 网络流

26.1-1

定义1:如果(u,v)不属于E,c(u,v)=0性质1:f(u,v) <= c(u,v)====> 如果(u,v)不属于E,f(u,v) = 0。反向边同理

26.1-2
性质2,反对称性
26.1-3
待解决
26.1-4

26.1-5

(1)f(X,Y)=-f(V-X,Y)X:t   Y:v3,v4(2)f(X,Y)!=-f(V-X,Y)X:v3,v4  Y:v1,v2

26.1-6
必定满足“反对称性”和“流守恒性”,可能违反“容量限制”
26.1-7

由26.1-6知,af1+(1-a)f2满足“反对称性”和“流守恒性”。因为f1和f2满足“容量限制”,因此af1+(1-a)f2满足“容量限制”所以af1+(1-a)f2也是流

26.1-8
在网络中每一节点流入流出的量应该相等

无标题 

例如上图,可以写出以下等式:

x1 – x3 –x4 = 0

x2 + x3 – x5 = 0
26.1-9

将地图转换为一个有向图:(1)每个角落作为一个顶点(2)若一个角落到另一个角落有路,则构成有向图的边。(3)每条路构成正向和反向两条边,容量都是1计算该有向图的最大流,若最大流大于或等于2,则“可以”

26.2Ford-Fulkerson方法

26.2-1

净流:19

容量:31

26.2-2

IMG_3679

 

26.2-3最大流的最小割是23第二条增广路径的第二段和第三条增广路径的第2段抵消
第一条增广路径的第三段和第四条增广路径的第2段抵消26.2-4根据反对称性和残留网络定义
    c|f(u,v) + c|f(v,u) =    c(u,v) - f(u,v) + c(v,u) - f(v,u) =    c(u,v) + c(v,u) 26.2-5
根据流守恒

26.2-6

 IMG_3678

26.2-7

似乎是很显然的事情

26.2-8

不知道题目是什么意思,讨厌证明题

26.2-9

构造这样一个带权有向图G2,

G2的顶点和G是一样的。若G中存在一条(u,v)的边,则在G2中加一条u->v的边,和一条v->u的边,权值都是1.

在G2的基础上构造|V|个网络流,依次令|V|个顶点分别做为汇点,再选一个不是汇点的点做为源点。依次求这|V|个网络流的最大流。

这|V|个网络流的最小值即为G的边连通度

26.3最大二分匹配

26.3-1

IMG_3680

26.3-2

又见证明题

26.3-3

2*min(|L|, |R|)+1

26.4 压入与重标记法

26.5重标记与前移算法

四、思考题

26-1逃脱问题

(1)构造网络流G,令m个点为G的源点,令边界点中不是源点的点为G的汇点。

(2)若两个顶点相邻,则构造两条有向边,边权为1

26-2最小路径覆盖

26-3航天飞机实验

26-4最大流的更新
26-5用定标法计算最大流

26-6具有负容量的最大流

26-7Hopcroft-Karp二分图匹配算法