最大网络流Edmond-Karp算法

#include<iostream>

using namespace std;

const int MAXV=2000;   //最大顶点数量 
const int MAXE=2000;   //最大边数量
const int INFINITY = 0x7fffffff;   //无穷大 
int capacity[MAXV][MAXV]; //记录残流网络的容量
int flow[MAXV];  //标记从源点到当前节点实际还剩多少流量可用
int pre[MAXV];  //标记在这条路径上当前节点的前驱,同时标记该节点是否在队列中
int Queue[MAXV];   //求最短增广路算法需要用到的队列 

int MaxFlow(int src, int des, int n);
int Edmonds_Karp(int src, int des, int n);

int main()
{
	int  m, n, u, v;

	printf("请输入顶点数量:"); 
    scanf("%d", &n);
    printf("\n请输入边数量:"); 
    scanf("%d", &m);
 
	for(int i=0; i<m; ++i)
    {
        cin >> u >> v;
        cin >> capacity[u][v];    
    }
    
    cout << MaxFlow(0, n-1, n) << endl;

    system("pause");				   
	return 0;
}

int MaxFlow(int src, int des, int n)
{
 	int sumFlow = 0; //存储 src到des的最大流 
 	int inc = 0; //存储最短增广路的流量增量
 	int u, v;
	
	while (inc=Edmonds_Karp(src, des, n) != -1)
	{
        //逆向调整增广路(即修改对应残流网络的容量)
        v = des;
        while (v != src)
        {
            u = pre[v];
            capacity[u][v] -= inc;
            capacity[v][u] += inc;
            v = u;
        }
        
        sumFlow += inc;
    }
    
    return sumFlow;
}

int Edmonds_Karp(int src, int des, int n)//广度优先搜索寻找最短增广路 
{
 	int u, front = 0, rear = 0; //清空队列 
 	
 	for(int i=0; i<n; ++i) //初始化列表 
    {
	    pre[i] = -1;
    }
 	//源点加入队列
 	flow[src] = INFINITY;
 	pre[src] = src;
 	Queue[rear++] = src;
 	
 	while (front < rear) //队列非空
	{
        u = Queue[front++];
        for(int i=0; i<n; ++i) //寻找未访问过的邻接点,并计算最小增加流量 
        {
	        if (pre[i] == -1 && capacity[u][i])
	        {
   		        pre[i] = u;
   		        flow[i] = (flow[u] < capacity[u][i]) ? flow[u] : capacity[u][i];
   		        
   		        if (i == des) //找到汇点,直接返回最小增加流量  
   		        {
		   	        return flow[des];
                }
                
   		        Queue[rear++] = i;
   		    }
	    }
    } 
    
    //判断残流网络中是否存在增广路径
    return (pre[des] == -1) ? -1 : flow[des];
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值