• 最大流问题


    对最大流问题比较感性的认识,要看证明还是要看算法导论的相关章节。
    最大流问题:
    给定一个有向图,一般情况下边的值为整数,定义不直接相连的节点间的边值为0,如果有节点i和j直接由多条边,则将这些边合并为一条,值取和。则若i到j有边,则j到i的边为0,这些边称为反向边。定义其中的两个点位源点和汇点,则这个有向图可以视为流网络。网络中的有向边的值表示可以通过该边的最大流量,最大流问题就是求从源点出发,流进汇点的最大流量。
    为了求最大流,必须了解残余网络,增广路径,反向弧等概念。
    残余网络是针对流网络的某个状态而定义的。
    如图是一个流网络的状态,其中1为源点,7为汇点,每天边的值为v/c的形式表示,v代表当前状态该边上的实际流量,c代表该边的最大流量:

    则它的残余网络就是从中找到一个从源点到汇点的路径(该路径中不存在值为0的边),选取这条路径中v的最小值minflow,也就是该路径的实际流量,然后将该路径的所有边的实际容量都更新为c(i,j)-minflow,并修改其反向边的值为c(j,i)+minflow(这一步的意义可能是直接的贪心求法无法得到最优解,需要增加方向边来修正错误?)。这样的一条路径称为增广路径,修改值后的流网络成为残留网络。增广路径的意义在于能给当前最大流增加多少的值,而残余网络的意义在于每个节点从源点的流入量还能增加多少,0表示不能再增加了。当残留网络中没有增光路经时,则当前流入汇点的流值为最大流。
    下图是找到两条增光路经,并修改流网络后的残余网络(我感觉此时3到4,5到6和6到7之间应该仍然为0):

    以上方法为Ford-Fulkerson方法,该方法的一种实现是基于BFS的Edmonds-Karp算法。

    算法流程如下:

      设队列Q:存储当前未访问的节点,队首节点出队后,成为已检查的标点;

      Path数组:存储当前已访问过的节点的增广路径;

      Flow数组:存储一次BFS遍历之后流的可改进量;

      Repeat:

        Path清空;

        源点S进入Path和Q,Path[S]<-0,Flow[S]<-+∞;

        While Q非空 and 汇点T未访问 do

            Begin

                队首顶点u出对;

                For每一条从u出发的弧(u,v) do

                    If v未访问 and 弧(u,v) 的流量可改进;

                    Then Flow[v]<-min(Flow[u],c[u][v]) and v入队 and Path[v]<-u;

        End while

       

        If(汇点T已访问)

        Then 从汇点T沿着Path构造残余网络;

      Until 汇点T未被访问


    POJ上一到入门级的最大流问题:例题: http://poj.org/problem?id=1273

    例题的代码实现,基本仿照参考链接:
    说明:
    start:源点
    terminal:汇点
    map[LEN][LEN]:流网络
    bfsqueue:每一状态中,用BFS最增广路经,每次只求一条增广路径
    minflow[LEN]:记录从源点流入每个点的最大可能值,这个值也将该路径中的最小值(该路径的实际流量)一直传递到汇点。该值是每次BFS都要保留的
    path[LEN]:记录增广路径,其中path[j] = i表示从节点 i 流向节点 j 。同时也记录了每次bfs时记录是否考察了当前节点。

    每次BFS完后,查看path[terminal],如果path[terminal]==-1,则表示没有从源点到汇点的增广路径了。
    每次BFS完后,要更新增广路径中的容量和方向路径的容量,因为minflow已经记录了增光路经中的最小值,用minflow[terminal]更新即可。

    #define LEN 201
    int map[LEN][LEN];
    int minflow[LEN];
    int n,m;
    int start;
    int terminal;
    queue< int> bfsqueue;
    int bfs(int path[LEN]){
                    memset(path,-1, sizeof (int )*LEN);
                     while (!bfsqueue.empty()) bfsqueue.pop();
                    path[start] = 0;
                    minflow[start] = MAXINT;
                    bfsqueue.push(start);
                     while (!bfsqueue.empty()){
                                     int node = bfsqueue.front();
                                    bfsqueue.pop();
                                     for (int i=1;i<=m;++i){
                                                     if (path[i] == -1 && map[node][i]!=0 && i != start){
                                                                    minflow[i] = (minflow[node]<map[node][i])?minflow[node]:map[node][i];
                                                                    path[i] = node;
                                                                    bfsqueue.push(i);
                                                    }
                                    }
                    }
                     if (path[terminal] == -1)         return -1;
                     return minflow[terminal];
    }
    int edmonds_karp(){
                     int max_flow = 0;
                     int path[LEN];
                     int increasedflow;
                     int node;
                     while ( (increasedflow=bfs(path)) != -1){
                                    max_flow += increasedflow;
                                    node = terminal;
                                     while (node != start){
                                                     int pre = path[node];
                                                    map[pre][node] -= increasedflow;
                                                    map[node][pre] += increasedflow;
                                                    node = pre;
                                    }
                    }
                     return max_flow;
    }
    



  • 相关阅读:
    孙权用人之道:“六力”兼备
    JDK 自带工具试用(一)
    Apache ab 测试工具使用(一)
    Amoeba详细介绍
    TCP/IP 标志位 SYN ACK RST UTG PSH FIN
    ERROR 1044 (42000): Access denied for user ''@'localhost' to database 'mysql'
    jsp 中声明方法的使用
    Java遍历一个文件夹下的全部文件
    WAMP 2.5 &quot;FORBIDDEN&quot; error
    LeetCode总结--二分查找篇
  • 原文地址:https://www.cnblogs.com/james1207/p/3315480.html
Copyright © 2020-2023  润新知