Edmonds-Karp算法,网络流最大流

来源:互联网 发布:数据的指标分析体系 编辑:程序博客网 时间:2024/04/28 14:20

     网络流是一种生活中常见的图模型,包含一个起始点,和一个汇点,以及若干结点,用有向边连接,每条边的权值代表能流经该边的最大流量。生活中,水流网络,电流网络,信息网络这些问题都能描述成网络流。网络流中一种常见的问题是最大流问题。即求从起始点到达汇点流的最大值。在《算法导论》介绍了Edmonds-Karp算法,该算法运行时间在图G=(V,E)上为O(VE),基于BFS实现。

     实现过程是从残存网络中找到一条最短的增广路径,对路径上的边做增广操作,并改变一些数据,直到残存网络中不在存在增广路径。

     残存网络简单来讲就是在每次增加操作结束后得到的网络,原本在网络流中不允许出现平行反向的边(若map[u][v]为网络流中的一条边,那么网络流中必然不存在map[v][u],map[v][u]为map[u][v]的平行反向边,画图的话会很好理解)。但是在残存网络中需要加入反向平行边(如果有必要)。每条边的权值表示可通过该边的流量,那么在残存网络中,反向平行边的权值代表的是原本已经流过该边的流量。例如:f[u][v]=x代表已经流过该边的流量,那么,map[v][u]的权值就为f[u][v]。可以看出,未做任何操作的流网络也是一个残存网络。

增广路径就是在残存网络中可以从起始点走到汇点(想了一下,可能叫目标点会更好理解?)的一条简单路径。如图,1-->2-->4-->6为一条增广路径。


     接下来就是每次找到增广路径以后对路径上每条边做处理了c[u][v]代表边uàv的能通过的最大流量或者叫做容量。首先需要找到该路径的增加流量,该流量值为该路径上所有边中残存流量的最小值,这是保证可以通过该路径的最大流量值。接下来需要缩减通过该边的容量,同时需要增加平行反向边的容量。记增加流量为p,那么u-->v为该路径上的边。c[u][v]-=p;c[v][u]+=p。

按照这样的操作直到不存在增广路径。

#include<iostream>#include<cstring>#include<cstdio>#include<cmath>using namespace std;int path[1000005],flow[1000005];int map[1005][1005],que[1000005];int n,m;int BFS(int start,int des){    int head,tail;    memset(que,0,sizeof que);    for (int i=1;i<=n;i++)    {        path[i]=-1;    }    path[start]=0;    flow[start]=0x3f3f3f3f;    head=tail=0;    que[head++]=start;    while (head>tail)    {        int u=que[tail++];        if (u==des)            break;        for (int i=1;i<=n;i++)        {            if (i!=str&&path[i]==-1&&map[u][i]>0)            {                path[i]=u;                flow[i]=min(map[u][i],flow[u]);                que[head++]=i;            }        }    }    if (path[des]==-1)        return -1;    return flow[des];}int maxflow(int start,int des){    int sum=0,increase=0;    while ((increase=BFS(start,des))!=-1)    {        int k=des;        while (k!=start)        {            int pre=path[k];            map[pre][k]-=increase;            map[k][pre]+=increase;            k=pre;        }        sum+=increase;    }    return sum;}int main(){    int start,end,f;    while (cin>>n>>m)      {        memset(map,0,sizeof map);        for (int i=0;i<m;i++)        {            cin>>start>>end>>f;            map[start][end]+=f;        }        cin>>start>>end;        int ans=maxflow(start,end);        cout<<ans<<endl;    }}

1 0