最大流的Edmonds-Karp算法

本文深入探讨了最大流问题的高效求解方法——Edmonds-Karp算法,通过类比水流过程,详细解释了如何在图中寻找增广路径并更新残余网络,直至无法找到新路径为止,从而得到最大流。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最大流的问题描述可以对比参照水在水管中的流动。从源(图中唯一的入度为0的点)流到汇(图中唯一出度为0的点)。每条水管都有限定的容量,要求最多能有“多少”水同时流动到汇。

最大流的一种比较优的解法时Edmonds-Karp算法,不断找一条源到汇的路径,若有,找出增广路径上每一段[容量-流量]的最小值delta,然后构建残余网络,再在残余网络上寻找新的路径,增加总流量,形成新的残余网络,再寻找新路径…..直到某个残余网络上找不到从源到汇的路径为止,最大流就算出来了。通俗来说,当我们通过搜索找到一条从起点(源)到终点(汇)的路径后,我们把路径上每条正向边都减掉算出来的流量值,同时反向边加上算出来的流量值,然后再次搜索找新的路径直到没有办法找到,每次都加上搜索出来的流量值即可。

附上代码:



#include <iostream>  
#include <queue>  
#include<cstring> 
#include<cstdlib>
#include<cstdio>
#include<algorithm> 
using namespace std;  
#define arraysize 201  
int maxData = 0x7fffffff;  
int capacity[arraysize][arraysize]; //记录残留网络的容量  
int flow[arraysize];      //标记流动到当前节点后还有多少流量可以流动
int pre[arraysize];       //标记在这条路径上当前节点的前驱,同时标记该节点是否在队列中  
int n,m;  
queue<int> Q;  
int BFS(int s,int t)  
{   
    while(!Q.empty())       //队列清空  
        Q.pop();  
    for(int i=1;i<m+1;++i)  
    pre[i]=-1;  
    pre[s]=0;  
    flow[s]= maxData;  
    Q.push(s);  
    while(!Q.empty())  
    {  
        int index = Q.front();  
        Q.pop();  
        if(index == t)            //找到了增广路径  
            break;  
        for(i=1;i<m+1;++i)  
        {  
            if(i!=s && capacity[index][i]>0 && pre[i]==-1)  
            {  
                 pre[i] = index; //记录前驱  
                 flow[i] = min(capacity[index][i],flow[index]);   //关键:迭代的找到增量  
                 Q.push(i);  
            }  
        }  
    }  
    if(pre[t]==-1)      //残留图中不再存在增广路径  
        return -1;  
        return flow[t];  
}  
int maxFlow(int s,int t)  
{  
    int incr= 0;  
    int sum= 0;  
    while((incr=BFS(s,t))!=-1)  
    {  
         int k = t;          //利用前驱寻找路径  
         while(k!=s)  
         {  
              int last = pre[k];  
              capacity[last][k] -= incr; //改变正向边的容量  
              capacity[k][last] += incr; //改变反向边的容量  
              k = last;  
         }  
         sum += incr;  
    }  
    return sum;  
}  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值