网络流之最大流的增广路径算法

扩展:多路增广

一般的,在执行增广路算法时,都是先用BFS或DFS从源到汇找到一条增广路,记录下应修改的流量,然后再顺着路倒回去增广.反复这个过程直到增广路找不到了为止.
 
显然的,我们做了很多无用功,假设有两条很长的增广路,前面大部分都是重叠的,只是在最后关头分了个岔,而程序却把前面很长的路走了两次.
 
为什么要这样?
 
不妨把两条增广路合并起来,不止是两条,所有的增广路都可以按其前缀合并起来,而形成一棵增广树.找增广树可以用DFS,正如生成搜索树一样.
最大流增广路算法的扩展,多路增广
 
简而言之,对于当前的每一个结点记录一个可提供的最大流量,源点的可供流量显然是无穷大,当推到下一个点时,最大流量取边的容量和上个点提供的最大流量的较小值.
 
当到达汇点时,自然DFS开始回朔,这时按当前点的已用流量增广当前点与他父亲相连的边,同时将增广值累加到他父亲的已用流量上,并在他父亲的可提供流量上减掉这个值,以便在搜索他父亲剩下的儿子时,让所有儿子的已用流量总和不大于父亲的可提供流量,不然就出错了.
 
我们按照以下步骤做:
search node(available)
{
  1.得到node的可提供流量available
  2.search node's all son(可提供流量)
    {
        inc(已用流量,当前儿子实际增广的流量)
        dec(可提供流量,<同上>)
    }
  3.用得到的已用流量的值增广边(node-node's father)
  4.return 边的增广量 到 node'fahter
}
 
每进行一次以上步骤,我们就完成了一次多路增广,并且返回了一个值到源点,即DFS的根.这个值表示本次操作中将流量扩大了多少.重复操作直到返回值为0.得到最大流的数值即累加每次的返回值.
 

SAP(最短增广路算法) 最大流模板

#include <iostream>
#include <queue>
#define msize 1024      //最大顶点数目
using namespace std;
 
int d[msize];           //标号
int r[msize][msize];    //残留网络,初始为原图
int num[msize];         //num[i]表示标号为i的顶点数有多少
int pre[msize];
int n,m,s,t;            //m个顶点,n条边,从源点s到汇点t
 
void ini_d() //BFS计算标号,汇点t标号为0
{
    int k;
    queue<int>Q;
 
    memset(d,1,sizeof(d));
    memset(num,0,sizeof(num));
 
    Q.push(t);
    d[t]=0;
    num[0]=1;
    while (!Q.empty())
    {
        k=Q.front(),Q.pop();
        for (int i=0;i<m;i++)
        {
            if (d[i]>=m&&r[i][k]>0)
            {
                d[i]=d[k]+1;
                Q.push(i);
                num[d[i]]++;
            }
        }
    }
}
 
int findAlowArc(

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值