• 第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 210
    
    class 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 = 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 10
    0 1 16
    0 2 13
    1 3 12
    1 2 10
    2 1 4
    3 2 9
    2 4 14
    3 5 20
    4 3 7
    4 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 10
    0 1 16
    0 2 13
    1 3 12
    1 2 10
    2 1 4
    3 2 9
    2 4 14
    3 5 20
    4 3 7
    4 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二分图匹配算法

  • 相关阅读:
    不同权限访问详细细节
    文件搜索器
    java中依赖、关联、聚合
    子类重写父类成员方法
    java中子类对父类中的私有变量和私有方法有拥有权无使用权
    shell脚本在CentOS7自动更包
    LR虚拟用户已设置集合点,但controller无法设置集合点策略的解决方案
    LR工具使用之场景设置
    LR集合点策略
    LR录制附件上传后,回放报错
  • 原文地址:https://www.cnblogs.com/windmissing/p/3787544.html
Copyright © 2020-2023  润新知