您的位置:首页 > 理论基础 > 计算机网络

最大流-EK(Edmond—Karp)算法

2017-07-25 21:16 429 查看
在图论中,网络流是指在一个每条边都有容量(capacity)的有向图分配流,使一条边的流量不会超过它的容量。

关于增广路:

存在一条分流能够达到汇点,流量为分流中边残余容量的最小值。

关于反向弧:

相当于当另一条分流也走到这个节点时,将多出来的一部分流量推回至其前驱节点并流向前驱节点的另外一条分支。

详细请看:http://blog.csdn.net/fobdddf/article/details/19611065

先贴一份模板

#include <iostream>
#include <queue>
#include<string.h>
using namespace std;
#define arraysize 201
int maxData = 0x7fffffff;
int capacity[arraysize][arraysize]; //记录残留网络的容量
int flow[arraysize];                //标记从源点到当前节点实际还剩多少流量可用
int pre[arraysize];                 //标记在这条路径上当前节点的前驱,同时标记该节点是否在队列中
int n,m;
queue<int> myqueue;
int BFS(int src,int des)//每次尝试找一条增广路
{
int i,j;
while(!myqueue.empty())       //队列清空
myqueue.pop();
for(i=1;i<m+1;++i)//将所有点的前驱节点初始化为-1
{
pre[i]=-1;
}
pre[src]=0;//源点的前驱为0
flow[src]= maxData;//将源点的存储容量初始化为无穷大
myqueue.push(src);//将源点入队
while(!myqueue.empty())
{
int index = myqueue.front();
myqueue.pop();
if(index == des)            //找到了增广路径
break;
for(i=1;i<m+1;++i)
{
if(i!=src && capacity[index][i]>0 && pre[i]==-1)//如果当前路径残余容量大于0,且这个节点没有被访问过
{
pre[i] = index; //记录前驱
flow[i] = min(capacity[index][i],flow[index]);   //关键:迭代的找到增量,这条增广路的流量取路径残余容量和前驱节点的已有体积的最小值
myqueue.push(i);
}
}
}
if(pre[des]==-1)      //残留图中不再存在增广路径
return -1;
else
return flow[des];//如果存在增广路,则返回这条路的流量
}
int maxFlow(int src,int des)
{
int increasement= 0;
int sumflow = 0;
while((increasement=BFS(src,des))!=-1)//如果找到一条增广路
{
int k = des;          //利用前驱寻找路径
while(k!=src)
{
int last = pre[k];
capacity[last][k] -= increasement; //改变正向边的容量
capacity[k][last] += increasement; //改变反向边的容量
k = last;
}
sumflow += increasement;
}
return sumflow;
}
int main()
{
int i,j;
int start,end,ci;
while(cin>>n>>m)
{
memset(capacity,0,sizeof(capacity));
memset(flow,0,sizeof(flow));
for(i=0;i<n;++i)
{
cin>>start>>end>>ci;
if(start == end)               //考虑起点终点相同的情况
continue;
capacity[start][end] +=ci;     //此处注意可能出现多条同一起点终点的情况
}
cout<<maxFlow(1,m)<<endl;
}
return 0;
}

例题:Drainage Ditches

代码:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<queue>
using namespace std;
#define inf 1<<29
int n,m;
int G[205][205];//残余容量图
int flow[205];//分流到这个点的最大流量
int pre[205];//记录前驱节点
int maxflow;
int bfs(int scr,int des)
{
queue<int> q;
maxflow=0;
while(1)
{
while(!q.empty())
q.pop();
memset(pre,-1,sizeof(pre));
pre[scr]=0;
flow[scr]=inf;
q.push(scr);
while(!q.empty())
{
int top=q.front(); q.pop();
if(top==des)
break;
for(int i=1;i<=m;i++)
{
if(i!=scr && pre[i]==-1 && G[top][i]>0)
{
pre[i]=top;
flow[i]=min(flow[top],G[top][i]);
q.push(i);
}
}
}
if(pre[des]==-1)
break;
int tmp=des,increase=flow[des];
//printf("->%d\n",increase);
while(tmp!=scr)
{
int last=pre[tmp];
G[last][tmp]-=increase;
G[tmp][last]+=increase;
tmp=last;
}
maxflow+=increase;
}
return maxflow;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
memset(G,0,sizeof(G));
memset(flow,0,sizeof(flow));
int u,v,w;
for(int i=0;i<n;i++)
{
scanf("%d%d%d",&u,&v,&w);
G[u][v]+=w;
}
printf("%d\n",bfs(1,m));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息