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

最大流最小割算法; BFS搜索增广路径; 算法简单,打印结果也比较清晰;

2010-06-17 14:55 363 查看
#include <iostream>
#include <queue>
using namespace std;

/*********************************/
* 最小割最大流算法
* 可以在求得最大流的同时获取最小割集S,T
* 邻接矩阵存储各类信息
/*********************************/
#define INF 1000000

const int MAXN=1000;
int cap[MAXN][MAXN]; //容量 ,没有边为0
int flow[MAXN][MAXN]; //流量
int a[MAXN]; //增广路径上最小残流
int p[MAXN]; //增广路前驱
int n; // 顶点数目
int f; //最大流
int s,t; //源点,汇点

/*********************************/
*  邻接矩阵读入图数据
*  例子:
0 16 13 0 0 0
0 0 10 12 0 0
0 4 0 0 14 0
0 0 9 0 0 20
0 0 0 7 0 4
0 0 0 0 0 0
/*********************************/
void readG()
{
cin>>n;
for(int i=0;i<n;++i)
{
for(int j=0;j<n;++j)
{
cin>>cap[i][j];
}
}
}

/*********************************/
* EdmondsKarp() 最大流最小割算法
* BFS搜索增广路
/*********************************/

void EdmondsKarp()
{
cin>>s>>t;

queue<int> q;
memset(flow,0,sizeof(flow));
f=0;

for(;;)
{
memset(a,0,sizeof(a));
a[s]=INF;
q.push(s);
while(!q.empty())
{
int u=q.front(); q.pop();
for(int v=0;v<n;++v)
{
if(!a[v]&&cap[u][v]-flow[u][v]>0)
{
p[v]=u;
a[v]= (cap[u][v]-flow[u][v]) < a[u] ?  (cap[u][v]-flow[u][v]) : a[u];
q.push(v);
}
}
}
//没有增广路,算法结束,打印最小割
if(!a[t])
{
cout<<"/n/n最小割集S:";
for(int i=0;i<n;++i)
{
if(a[i])
{
cout<<i<<",";
}
}
cout<<"/n最小割集T:";
for(int j=0;j<n;++j)
{
if(!a[j])
{
cout<<j<<",";
}
}
cout<<"/n最大流:"<<f<<endl;
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];
}
}
int main()
{
readG();
EdmondsKarp();
return 0;
}


 

 

由于BFS能够找到最短路,所以也就保证对于任何情形的图G,均可以在较少的次数内尽快到达汇点T,用DFS不太好.

 

每次找到一条增广路径, 就给这条路径增流 , 增加的流量就可以计入到最大流内了, 因为不可能从汇点T有回流,所以只要增流的都可以计入最大流. (流网络必须满足有源点和汇点,否则算法应该跑的结果是没有意义的).

 

初始化时, cap[i][i]=0.     cap[i][j]=0 , if(E[i][j]不属于流网络) .

 

用邻接矩阵存储比较方便, 但是输入量很大.

 

可以先用静态数组的邻接表录入所有存在容量的边, 然后初始化cap[][]全部为0, 然后根据邻接表, 把有容量的边的容量填到cap[][]里.

 

这样录入量会小很多, 不必整张cap矩阵都录入, 其中大量的0容量输起来真的很繁琐.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 include 存储 网络
相关文章推荐