网络流初步(Edmonds-Karp,Bellman-Ford)

网络流是一个适用范围相当广的模型,相关的算法也非常多。尽管如此,网络流中的概念,思想和基本算法并不难理解。

最大流问题(Maximum-Flow Problem)

增广路算法

算法思想:从零流(所有边的流量均为0)开始不断增加流量,保持每次增加流量后都满足容量限制(f(u,v)<=c(u,v),c表示最大流量,f表示实际流量),斜对称性(f(u,v)=-f(v,u))和流量平衡(除了终起点,其他点的入与出相等)3个条件

我们的算法基于这样的一个现实:残量网络中任何一条从s到t的有向道路都对应一条原图中的增广路(augmenting path)——只要求出该道路中所有残量的最小值d,把对应的所有边上的流量增加d即可,这个过程称为增广(augmenting).不难验证,如果增广前的流量满足3个条件,增广后仍然满足。显然,只要找到残量网络中存在增广路,流量就可增大。可以证明它的逆命题也成立:如果残量网络中不存在增广路,则当前流就是最大值。这就是著名的增广路定理。

“找任意路径”最简单的办法无疑是用DFS,但很容易找出让他很慢的例子。一个稍微好一些的方法就是使用BFS,它足以应对数据不刁钻的网络流题目。这就是Edmonds-Karp算法。在下面的代码中,源点和汇点保存在变量s和t中,运行结束后,s-t的净流量保存在变量f中。

queue<int> q;
memset(flow,0,sizeof(flow));
f=0;
for(;;)/每次用for循环找一条最短的增广路径
{
    memset(a, 0, sizeof(a));
    a[s]=INF;
    q.push(s);
    while(!q.empty()) //BFS找增广路
    {
        int u=q.front();q.pop();
        for(int v=1;v<=n;v++) if(!a[v]&& cap[u][v]>flow[u][v]) //找到新结点v
        {
            p[v]=u;q.push(v); //记录v的父亲,并加入FIFO队列
            a[v]=a[u]<?cap[u][v]-flow[u][v]; //s-v路径上的最小残量
        }
    }
    if(a[t]==0) break; //找不到,则当前流已经是最大流
    for(int u=t;u!=s;u=p[u]) //从汇点往回走
    {
        flow[p[u]][u]+=a[t];//更新正向流量
        flow[u][p[u]]-=a[t];//更新反向流量
    }
    f+=a[t];//更新从s流出的总流量
}

 

最小割最大流定理

 

 

最小费用最大流问题

 

queue<int> q;
int d[maxn];
memset(flow,0,sizeof(flow));
c=f=0;
for(;;)
{
    //bellman-ford算法开始(在残量网络中找s-t最短路)
    bool inq[maxn];
    for(int i=0;i<n;i++) d[i]=(i==s?0:INF);
    memset(inq,0 ,sizeof(inq));
    q.push(s);
    while(!q.empty())
    {
        int u=q.front();q.pop();
        inq[u]=false;
        for(int v=0;v<n;v++) if(cap[u][v]>flow[u][v]&& d[v]>d[u]+cost[u][v])
        {
            d[v]=d[u]+cost[u][v];
            p[v]=u;
            if(!inq[v])
            {
                inq[v]=true;
                q.push(v);
            }
        }
    }
    //bellman-ford算法到此结束
    
    if(d[t]==INF) break; //汇点不可达,表明当前流已经是最小费用最大流
    int a=INF;
    for(int u=t;u!=s;u=p[u]) a<?=cap[p[u]][u]-flow[p[u]][u]; //计算可改进量
    for(int u=t;u!=s;u=p[u]) //增广
    {
        flow[p[u]][u]+=a;
        flow[u][p[u]]-=a;
    }
    c+=d[t]*a;//更新总费用和流量
    f+=a;
}

 

    原文作者:Bellman - ford算法
    原文地址: https://blog.csdn.net/weixin_42373330/article/details/82944412
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞