在算法导论中对求解最大流问题给出了一般性的解决方法,但并没有涉及到具体的实现。在这里我还是重新的对求解最大流的思想进行一般性的描述,然后再给出具体的实现。

Ford-Fulkerson方法依赖于三种重要思想,这三个思想就是在上一篇网络流基础中提到的:残留网络,增广路径和割。Ford-Fulkerson方法是一种迭代的方法。开始时,对所有的u,v∈V有f(u,v)=0,即初始状态时流的值为0。在每次迭代中,可通过寻找一条“增广路径”来增加流值。增广路径可以看成是从源点s到汇点t之间的一条路径,沿该路径可以压入更多的流,从而增加流的值。反复进行这一过程,直至增广路径都被找出来,根据最大流最小割定理,当不包含增广路径时,f是G中的一个最大流。在算法导论中给出的Ford-Fulkerson实现代码如下:

FORD_FULKERSON(G,s,t)
     1   for each edge(u,v)∈E[G]
     2        do f[u,v] <— 0
     3            f[v,u] <— 0
     4   while there exists a path p from s to t in the residual network Gf
     5        do cf(p) <— min{ cf(u,v) : (u,v) is in p }
     6        for each edge(u,v) in p
     7             do f[u,v] <— f[u,v]+cf(p)         //对于在增广路径上的正向的边,加上增加的流
     8                  f[v,u] <— -f[u,v]                //对于反向的边,根据反对称性求

第1~3行初始化各条边的流为0,第4~8就是不断在残留网络Gf中寻找增广路径,并沿着增广路径的方向更新流的值,直到找不到增广路径为止。而最后的最大流也就是每次增加的流值cf(p)之和。在实际的实现过程中,我们可以对上述代码做些调整来达到更好的效果。如果我们采用上面的方法,我们就要保存两个数组,一个是每条边的容量数组c,一个就是上面的每条边的流值数组f,在增广路径中判断顶点u到v是否相同时我们必须判断c[u][v]-f[u][v]是否大于0,但是因为在寻找增广路径时是对残留网络进行查找,所以我们可以只保存一个数组c来表示残留网络的每条边的容量就可以了,这样我们在2~3行的初始化时,初始化每条边的残留网络的容量为G的每条边的容量(因为每条边的初始流值为0)。而更新时,改变7~8行的操作,对于在残留网络上的边(u,v)执行c[u][v]-=cf(p),而对其反向的边(v,u)执行c[v][u]+=cf(p)即可。

现在剩下的最关键问题就是如何寻找增广路径。而Ford-Fulkerson方法的运行时间也取决于如何确定第4行中的增广路径。如果选择的方法不好,就有可能每次增加的流非常少,而算法运行时间非常长,甚至无法终止。对增广路径的寻找方法的不同形成了求最大流的不同算法,这也是Ford-Fulkerson被称之为“方法”而不是“算法”的原因。下面将给出Ford-Fulkerson方法的具体实现细节:

int c[MAX][MAX];  //残留网络容量
int pre[MAX];  //保存增广路径上的点的前驱顶点
bool visit[MAX];

int Ford_Fulkerson(int src,int des,int n){   //src:源点 des:汇点 n:顶点个数
     int i,_min,total=0;
     while(true){
         if(!Augmenting_Path(src,des,n))return total; //如果找不到增广路就返回,在具体实现时替换函数名
         _min=(1<<30);
         i=des;
         while(i!=src){   //通过pre数组查找增广路径上的边,求出残留容量的最小值
             if(_min>c[pre[i]][i])_min=c[pre[i]][i];
             i=pre[i];
         }
         i=des;
         while(i!=src){    //再次遍历,更新增广路径上边的流值
             c[pre[i]][i]-=_min;
             c[i][pre[i]]+=_min;
             i=pre[i];
         }
         total+=_min;     //每次加上更新的值
     }
}


Edmonds-Karp算法实际上就是采用广度优先搜索来实现对增广路径的p的计算,代码如下:

bool Edmonds_Karp(int src,int des,int n){
     int v,i;
     for(i=0;i<n;i++)visit[i]=false;
     front=rear=0;     //初始化
     que[rear++]=src;
     visit[src]=true;
     while(front!=rear){     //将源点进队后开始广搜的操作
         v=que[front++];
         //这里如果采用邻接表的链表实现会有更好的效率,但是要注意(u,v)或(v,u)有任何一条
         //边存在于原网络流中,那么邻接表中既要包含(u,v)也要包含(v,u)
         for(i=0;i<n;i++){ 
             if(!visit[i]&&c[v][i]){  //只有残留容量大于0时才存在边
                 que[rear++]=i;
                 visit[i]=true;
                 pre[i]=v;
                 if(i==des)return true;   //如果已经到达汇点,说明存在增广路径返回true
             }
         }
     }
     return false;
}

Ford_Fulkerson算法相关推荐

  1. 匹配问题与匈牙利算法

    文章目录 匹配问题 实际意义 最大匹配 二部图中的完美匹配 匈牙利算法 用求解最大流问题的算法求解匹配问题 匹配问题 设MMM为图G=(V,E)G=(V, E)G=(V,E)的边集合的子集,即M⊆EM ...

  2. 对最大流算法Ford_Fulkerson的研究与理解(二)

    继对作者的程序有一定的理解过后,我将源程序的BFS改成DFS的实现 : public boolean DFS(int src, int des){   //从源点开始访问   Stack<Int ...

  3. 最大流问题与福特-富尔克森算法

    文章目录 最大流问题 福特-富尔克森算法 最大流最小割定理 最大流问题 在给定弧赋权的有向图D=(V, A)中有两个特殊的点,一个是源点s,一个是汇点t. 我们可以将弧e上的权值理解为管道的容量,这时 ...

  4. 网络流的最大流入门(从普通算法到dinic优化)

    网络流(network-flows)是一种类比水流的解决问题方法,与线性规划密切相关.网络流的理论和应用在不断发展.而我们今天要讲的就是网络流里的一种常见问题--最大流问题. 最大流问题(maximu ...

  5. golang通过RSA算法生成token,go从配置文件中注入密钥文件,go从文件中读取密钥文件,go RSA算法下token生成与解析;go java token共用

    RSA算法 token生成与解析 本文演示两种方式,一种是把密钥文件放在配置文件中,一种是把密钥文件本身放入项目或者容器中. 下面两种的区别在于私钥公钥的初始化, init方法,需要哪种取哪种. 通过 ...

  6. 通用解题法——回溯算法(理解+练习)

    积累算法经验,积累解题方法--回溯算法,你必须要掌握的解题方法! 什么是回溯算法呢? 回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就&quo ...

  7. 伍六七带你学算法 进阶篇-生命游戏

    有趣的算法题–生命游戏 难度-中等 根据 百度百科 ,生命游戏,简称为生命,是英国数学家约翰·何顿·康威在 1970 年发明的细胞自动机. 想要体验生命游戏的小伙伴可以到这里-->生命游戏 进入 ...

  8. 伍六七带你学算法 进阶篇-排序算法

    给定一个整数数组 nums,将该数组升序排列. 示例 1: 输入:[5,2,3,1] 输出:[1,2,3,5] 示例 2: 输入:[5,1,1,2,0,0] 输出:[0,0,1,1,2,5] 各排序算 ...

  9. 伍六七带你学算法 入门篇-卡牌分组

    力扣-914. 卡牌分组 难度-简单 这是一道非常有趣的题,提交通过率令人深思 ,思考它是不是一道简单的题- 开始正题: 给定一副牌,每张牌上都写着一个整数. 此时,你需要选定一个数字 X,使我们可以 ...

最新文章

  1. 使用编译器——Solidity中文文档(8)
  2. K项目轶事之开工第一天
  3. 第五百七十二、三天 how can I 坚持
  4. python能做什么游戏ll-一个简单的python game游戏
  5. IE6,IE7,FF等浏览器不兼容原因及解决办法(转)
  6. 解决 同时安装 python3,python2环境时,用pip安装 python3 包
  7. TraceView(profile) and Systrace
  8. SQl---基础整理6--数据库的创建
  9. 浏览器字体大小怎么调_音乐文件如何升降调
  10. android从本地服务器新浪云,GitHub - SinaCloudStorage/SinaStorage-SDK-Android: Android SDK For 新浪云存储...
  11. 本周leetcode刷题总结!(二叉树)
  12. 窗体点击,空白处隐藏(stopPropagation)
  13. 周六讲的题~C组木有Java组有的
  14. 娱乐篇第十期:互联网的事情you意思(十)
  15. OSPF 单区域配置实例学习记录
  16. 九八k用计算机打出来的音乐,背景音乐大全
  17. Java的随机数原理
  18. 笔记本电脑 编程_如何选择笔记本电脑进行编程
  19. Python Spider入门
  20. Ubuntu18.04 操作分屏显示快捷键

热门文章

  1. Failed to run the WC DB work queue associated with
  2. oppo锁屏断网设置在哪里呀_oppo手机不自动锁屏怎么设置怎么办
  3. 长达十五个小时的面试!程序员终极面试!
  4. (五)安装axios与最终效果——vue-cli3实例:电商分类网页
  5. 什么是软件著作权证书?安卓app上架要软件著作权吗
  6. matlab射频传输距离计算,Lora参数计算和RF射频传输距离计算公式和工具 - 创新实验室 - 电子工程世界-论坛 - 手机版...
  7. Java 根据IP获取城市(ip2region)
  8. FOXHIS西软系统sybase提示通知空间不足处理方法
  9. Python 入门指南 [闲聊]
  10. 卧槽,GitHub评分不错的开源项目,必须收藏!