实用算法实现-第 23 篇 最大流

23.1    Ford-Fullkerson方法

使用BFS来实现Ford-Fullkerson方法中的找增广路径的算法称为Edmods-Karp算法。Edmods-Karp算法是最短增广路算法,因为实用BFS找到的增广路径是所有可能的增广路径中最短的路径。它的复杂度是O(VE­­2­),其中V是结点数,E是有向边数。

如果用使用DFS代替BFS,则Ford-Fullkerson方法退化成一般增广路算法。其复杂度是O(E| f* |)。其中f*是算法找出的最大流。

23.2    最大流的Edmods-Karp算法

23.2.1   实例

PKU JudgeOnline, 1273, Drainage Ditches.

23.2.2   问题描述

给出M个点然后给出N条边的最大流量,求最大流。

23.2.3   输入

54

12 40

14 20

24 20

23 30

3 4 10

23.2.4   输出

50

23.2.5   分析

基本的最大流算法Edmonds-Karp就可以完成。

PKU JudgeOnline, 3436, ACM Computer Factory也是基本的最大流问题,只是构图需要花一点时间。

23.2.6   程序

#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
#define MAX   0x7FFFFFFF
int route[201][201];
int c[201][201];
int f[201][201];
struct queue{
     int parent;
     int node;
};
queuequeue[2000];
int last;
int visited[201];
int M;
void EdmondsKarp()
{
     int i, j;
     int temp;
     int from,to;
     intpointer;
     int minC;
     int parent;
     while(1){
         memset(visited, 0, sizeof(visited));
         last = 0;
         queue[last].parent = 0;
         queue[last++].node = 1;
         pointer = -1;
         for(i =0; i < last; i++){
              //BFS,找增广路径
              temp = queue[i].node;
              for(j= 1; j <= M; j++){
                   if((visited[j]== 0)&&
                       (c[temp][j] != 0))
                   {
                       visited[j] = 1;
                       queue[last].node = j;
                       queue[last++].parent = i;
                       if(j == M){
                            //到达汇结点,找到一条增广路径
                            pointer = last - 1;
                            break;
                       }
                   }
              }
              if(pointer!= -1)
              {
                   break;
              }
         }
         if(pointer== -1)
         {
              //没有找到增广路径
              break;
         }
         minC = MAX;
         temp = pointer;
         while(temp!= 0){
              //计算增光路径的流
              parent = queue[temp].parent;
              from = queue[parent].node;
              to = queue[temp].node;
              if(minC> c[from][to]){
                   minC = c[from][to];
              }
              temp = parent;
         }
         temp = pointer;
         while(temp!= 0){
              //修改残留网络
              parent = queue[temp].parent;
              from = queue[parent].node;
              to = queue[temp].node;
              c[from][to] = c[from][to] - minC;
              c[to][from] = c[to][from] + minC;
              f[from][to] = f[from][to] + minC;
              f[to][from] = -f[from][to];
              temp = parent;
         }
     }
}
int main()
{
     int N;
     int i;
     int temp;
     int from,to;
     int flow;
     while(cin>> N >> M){
         memset(c, 0, sizeof(c));
         memset(route, 0, sizeof(route));
         memset(f, 0, sizeof(f));
         for(i =0; i < N; i++){
              cin >> from >> to;
              cin >> temp;
              route[from][to] += temp;
              c[from][to] = route[from][to];
         }
         EdmondsKarp();
         flow = 0;
     
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值