第26章:最大流

原创 2016年05月31日 14:43:59

一:流网络

流网络G=(V,E)是一个有向图,图中每条边(u,v)有一个非负的容量值c(u,v)0。而且如果边集合E包含一条边(u,v),则图中不存在反方向的边(v,u)。如果边(u,v)不属于E,则定义c(u,v)=0,并且图中不允许自循环。在流网络的所有结点中,我们特别分别出两个特殊结点,源结点s和汇点t,为方便起见,假定每个结点都在从源点到汇点的某条路径上。

我们现在可以给出流的形式化定义。假设G=(V,E)为一个流网络,其容量函数为c。假设s为源结点,t为汇点。图中任意边(u,v)的流是一个实值f(u,v),其满足下面两个性质

1:容量限制:对于所有的结点u和v,要求0f(u,v)c(u,v)

2:流量守恒:对于属于集合V-{s,t}的所有结点u来说,要求vVf(v,u)=vVf(u,v)。当(u,v)E时,从结点u到结点v之间没有流,因此f(u,v)=0;

我们称非负数值f(u,v)为从结点u到结点v的流。一个流f的值|f|定义如下:

|f|=vVf(s,v)vVf(v,s)

也就是说,流f的值是从源结点流出的总流量减去流入源结点的总流量。在最大流问题中,给定一个流网络G,一个源结点s和一个汇点t,我们希望找到值最大的一个流。

二:Ford-Fulkerson方法

Ford-Fulkerson方法循环增加流的值。在开始的时候,对于所有的结点u,vV, f(u,v)=0,给出的初始流值为0。在每一次迭代中,我们将图G的流值进行增加,方法就是在一个关联的“残存网络”Gf中寻找一条“增广路径”。一旦知道残存网络中一条增广路径的边,就可以很容易辨别出G中的一些具体的边,我们可以对这些边上的流量进行修改,从而增加流的值。虽然Ford-Fulkerson方法的每次迭代都增加流的值,但是对于图G的一条特定边来说,其流量可能增加,也可能减少;对某些边的流进行缩减可能是必要的,以便让算法可以将更多的流从源结点发送到汇点。重复对流进行这一过程,直到残存网络中不再存在增广路径为止,这时候会获得一个最大流。

在残存网络中寻找增广路径的方法有很多种,下面的代码是用广度优先搜索寻找增广路径。代码如下:

//求从源点source到汇点sink的最大流量
double ford_fulkerson_bfs(const vector<list<int>>& graph,const vector<vector<double>>& capacity,int source,int sink)
{
        vector<list<int>> residual_network=graph; //residual_network表示残余网络;
        vector<vector<double>> c=capacity; //c表示残余网络每条边对应的容量;
        double max_flow=0; //从源点source到汇点sink的最大流量;
        double flow=0;

        vector<int> pred=bfs(residual_network,source); //表示用广度优先搜索方法得到的残余网络中从源>结点s到汇点t的简单路径,也就是残余网络中增广路径;
        const int NIL=-1;  //NIL表示不存在的顶点;
        while(pred[sink]!=NIL){
                flow=residual_capacity(pred,c,sink); //返回增广路径中的残存容量;
                max_flow+=flow;

                int vertex=sink;
                while(pred[vertex]!=-1){
                        int last_vertex=pred[vertex];

                        if(flow<c[last_vertex][vertex])
                                c[last_vertex][vertex]-=flow;
                        else{
                                c[last_vertex][vertex]=0;
                                remove_edge(residual_network,last_vertex,vertex);
                        }

                        if(c[vertex][last_vertex]!=0){
                                c[vertex][last_vertex]+=flow;
                        }
                        else{
                                add_edge(residual_network,vertex,last_vertex);
                                c[vertex][last_vertex]=flow;
                        }

                        vertex=last_vertex;
                }

                pred=bfs(residual_network,source);
        }

        print_edge_flow_value(graph,c); //输出从源点到汇点的最大流值在图中每条边的分配;
        return max_flow;
}

//上述代码中的residual_capacity(),add_edge(),remove_edge(),print_edge_flow_value()代码如下:

//残余网络的一条增广路径能够为每条边增加的流量的最大值,也就是增广路径所有边中容量的最小值;
double residual_capacity(const vector<int>& pred,const vector<vector<double>>& capacity,int sink)
{
        double flow=DBL_MAX;

        int vertex=sink;
        const int NIL=-1; //NIL表示不存在的顶点;
        while(pred[vertex]!=NIL){
                int last_vertex=pred[vertex];

                if(capacity[last_vertex][vertex]<flow)
                        flow=capacity[last_vertex][vertex];

                vertex=last_vertex;
        }

        return flow;
}

void remove_edge(vector<list<int>>& graph,int u,int v)
{
        auto iter=find(graph[u].begin(),graph[u].end(),v);
        graph[u].erase(iter);
}

void add_edge(vector<list<int>>& graph,int u,int v)
{
        graph[u].push_back(v);
}

void print_edge_flow_value(const vector<list<int>>& graph,const vector<vector<double>>& residual_network_capacity)
{
        for(int u=0;u!=graph.size();++u)
                for(auto iter=graph[u].begin();iter!=graph[u].end();++iter)
                {
                        int v=*iter;

                        cout<<"edge( "<<u<<", "<<v<<") flow value: "<<residual_network_capacity[v][u]<<endl;
                }
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

最大流问题及Ford-Fulkerson方法

流网络流网络是一个有向图,G=(V,E)G=(V,E),图中的每条边有一个非负的容量值c(u,v)≥0c(u,v)\geq 0.如果(u,v)∉E(u,v) \notin E,则定义c(u,v)=0c...

网络流(一) 入门到熟练

一.网络流:流&网络&割 1.网络流问题(NetWork Flow Problem): 给定指定的一个有向图,其中有两个特殊的点源S(Sources)和汇T(Sinks),每条边有指定的容量(Capa...

[c++]最大流算法

最大流算法转自 :http://www.cnblogs.com/hxsyl/p/4185530.html一、概念引入 首先要先清楚最大流的含义,就是说从源点到经过的所有路径的最终到达汇点...

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

一、综述 1.定义 定义1:流网络 定义2:残留容量 定义3:增广路径 已知一个网络流G=(V,E)和流f,增广路径p为残留网络G|f中从s到t的一条简单路径 能够沿一条增广路径p...

最大流高级算法

  • 2012年09月14日 11:24
  • 578KB
  • 下载

最大流dinic算法

  • 2015年12月06日 14:41
  • 1KB
  • 下载

【POJ3281】Dining【最大流】

【题目链接】 论文题,见【网络流建模汇总】。 注意下标要算对。 /* Pigonometry */ #include #include using namespace std; ...

最大流问题

  • 2014年07月05日 22:40
  • 3KB
  • 下载

HDU 3488--Tour【最小费用最大流 && 有向环最小权值覆盖 && 经典】

Tour Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Total Submi...
  • hpuhjh
  • hpuhjh
  • 2015年08月28日 00:17
  • 2033
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:第26章:最大流
举报原因:
原因补充:

(最多只允许输入30个字)