算法导论——26.2 FordFulkerson方法,Edmonds-Karp算法java实现

2024-03-30 04:48

本文主要是介绍算法导论——26.2 FordFulkerson方法,Edmonds-Karp算法java实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

介绍

由Ford 和Fulkerson于1956年提出最大流问题的标号算法,故又称 Ford–Fulkerson标号法。其基本思想就是,从一个可行流开始,寻找从s到t的增广链,然而沿增广链增加流量,反复这样,直到找不出增广链位置。

更多内容参见博文http://blog.csdn.net/smartxxyx/article/details/9293665

这里值得注意的是,这个方法各种实现算法不同,基本上都取决于增广路径的寻找方式不同,而用bfs的方式找增广路径的方法就是Edmonds-Karp算法,这里借鉴了http://blog.csdn.net/smartxxyx/article/details/9293805的代码,并且对其做了注释,得到以下java代码。

package algorithms.maxflow;import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;/*** @Description FordFulkerson方法中用edmondsKarp算法* Created with IntelliJ IDEA.* Created by The_Sam on 2017/5/9 11:27*/
public class FordFulkerson {private double residualNetwork[][] = null;private double flowNetwork[][] = null;int parent[];           //先驱节点/*** @param args*/public static void main(String[] args) {double graph[][] = {{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}};double graph2[][] = {{0, 1000000, 1000000, 0},{0, 0, 1, 1000000},{0, 0, 0, 1000000},{0, 0, 0, 0},};FordFulkerson ff = new FordFulkerson();System.out.println(ff.edmondsKarpMaxFlow(graph2, 0, 3));}/*** 实现FordFulkerson方法的一种算法——edmondsKarp算法** @param graph* @param s* @param t* @return*/public double edmondsKarpMaxFlow(double graph[][], int s, int t) {// this.N = graph.length;int length = graph.length;parent = new int[length];double f[][] = new double[length][length];;  //网络流for (int i = 0; i < length; i++) {Arrays.fill(f[i], 0);}double r[][] = residualNetwork(graph, f);          //计算残余网络double result = augmentPath(r, s, t);  //广度优先遍历,在残余网络中寻找增光路径,也是最短增广路径,得出该路径的流double sum = 0;while (result != -1) {int cur = t;while (cur != s) {//由后往前更新增广路径的流和残余网络f[parent[cur]][cur] += result;f[cur][parent[cur]] = -f[parent[cur]][cur];r[parent[cur]][cur] -= result;r[cur][parent[cur]] += result;cur = parent[cur];}sum += result;                      //最大流更新result = augmentPath(r, s, t);      //广度优先遍历,在残余网络中寻找增光路径,也是最短增广路径,得出该路径的流}residualNetwork = r;flowNetwork = f;return sum;}/*** deepCopy     残余网络计算** @param cost* @param f* @return*/private double[][] residualNetwork(double cost[][], double f[][]) {int length = cost.length;double r[][] = new double[length][length];for (int i = 0; i < length; i++) {for (int j = 0; j < length; j++) {r[i][j] = cost[i][j] - f[i][j];//残余网络=图cost-流f}}return r;}/*** 广度优先遍历,寻找增光路径,也是最短增广路径** @param graph* @param s* @param t* @return double 没有增广路径返回-1*/public double augmentPath(double graph[][], int s, int t) {double maxflow = Integer.MAX_VALUE;Arrays.fill(parent, -1);Queue<Integer> queue = new LinkedList<Integer>();queue.add(s);parent[s] = s;while (!queue.isEmpty()) {int p = queue.poll();if (p == t) {//如果到t了,则说明有了一条增广路径,则记录下该路径最小流,记为该增广路径可通过的最大流while (p != s) {if (maxflow > graph[parent[p]][p])maxflow = graph[parent[p]][p];p = parent[p];}} else { //记录最前面的前驱节点,如果没到最后t,切该节点没有记录过前驱节点,则记录该节点的前驱节点for (int i = 0; i < graph.length; i++) {if (i != p && parent[i] == -1 && graph[p][i] > 0) {//如果存在edge(p,i) 则记录parent[i]=p//flow[i]=Math.min(flow[p], graph[p][i]);parent[i] = p;queue.add(i);}}}}if (parent[t] == -1)//如果没有遍历到t节点,则不存在增广路径,返回-1return -1;return maxflow;}public double[][] getResidualNetwork() {return residualNetwork;}public double[][] getFlowNetwork() {return flowNetwork;}
}





这篇关于算法导论——26.2 FordFulkerson方法,Edmonds-Karp算法java实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/860513

相关文章

springboot rocketmq配置生产者和消息者的步骤

《springbootrocketmq配置生产者和消息者的步骤》本文介绍了如何在SpringBoot中集成RocketMQ,包括添加依赖、配置application.yml、创建生产者和消费者,并展... 目录1. 添加依赖2. 配置application.yml3. 创建生产者4. 创建消费者5. 使用在

Spring Retry 实现乐观锁重试实践记录

《SpringRetry实现乐观锁重试实践记录》本文介绍了在秒杀商品SKU表中使用乐观锁和MybatisPlus配置乐观锁的方法,并分析了测试环境和生产环境的隔离级别对乐观锁的影响,通过简单验证,... 目录一、场景分析 二、简单验证 2.1、可重复读 2.2、读已提交 三、最佳实践 3.1、配置重试模板

Spring中@Lazy注解的使用技巧与实例解析

《Spring中@Lazy注解的使用技巧与实例解析》@Lazy注解在Spring框架中用于延迟Bean的初始化,优化应用启动性能,它不仅适用于@Bean和@Component,还可以用于注入点,通过将... 目录一、@Lazy注解的作用(一)延迟Bean的初始化(二)与@Autowired结合使用二、实例解

SpringBoot使用Jasypt对YML文件配置内容加密的方法(数据库密码加密)

《SpringBoot使用Jasypt对YML文件配置内容加密的方法(数据库密码加密)》本文介绍了如何在SpringBoot项目中使用Jasypt对application.yml文件中的敏感信息(如数... 目录SpringBoot使用Jasypt对YML文件配置内容进行加密(例:数据库密码加密)前言一、J

Java中有什么工具可以进行代码反编译详解

《Java中有什么工具可以进行代码反编译详解》:本文主要介绍Java中有什么工具可以进行代码反编译的相关资,料,包括JD-GUI、CFR、Procyon、Fernflower、Javap、Byte... 目录1.JD-GUI2.CFR3.Procyon Decompiler4.Fernflower5.Jav

Spring Boot 中正确地在异步线程中使用 HttpServletRequest的方法

《SpringBoot中正确地在异步线程中使用HttpServletRequest的方法》文章讨论了在SpringBoot中如何在异步线程中正确使用HttpServletRequest的问题,... 目录前言一、问题的来源:为什么异步线程中无法访问 HttpServletRequest?1. 请求上下文与线

在 Spring Boot 中使用异步线程时的 HttpServletRequest 复用问题记录

《在SpringBoot中使用异步线程时的HttpServletRequest复用问题记录》文章讨论了在SpringBoot中使用异步线程时,由于HttpServletRequest复用导致... 目录一、问题描述:异步线程操作导致请求复用时 Cookie 解析失败1. 场景背景2. 问题根源二、问题详细分

Java对象和JSON字符串之间的转换方法(全网最清晰)

《Java对象和JSON字符串之间的转换方法(全网最清晰)》:本文主要介绍如何在Java中使用Jackson库将对象转换为JSON字符串,并提供了一个简单的工具类示例,该工具类支持基本的转换功能,... 目录前言1. 引入 Jackson 依赖2. 创建 jsON 工具类3. 使用示例转换 Java 对象为

解读为什么@Autowired在属性上被警告,在setter方法上不被警告问题

《解读为什么@Autowired在属性上被警告,在setter方法上不被警告问题》在Spring开发中,@Autowired注解常用于实现依赖注入,它可以应用于类的属性、构造器或setter方法上,然... 目录1. 为什么 @Autowired 在属性上被警告?1.1 隐式依赖注入1.2 IDE 的警告:

SpringBoot快速接入OpenAI大模型的方法(JDK8)

《SpringBoot快速接入OpenAI大模型的方法(JDK8)》本文介绍了如何使用AI4J快速接入OpenAI大模型,并展示了如何实现流式与非流式的输出,以及对函数调用的使用,AI4J支持JDK8... 目录使用AI4J快速接入OpenAI大模型介绍AI4J-github快速使用创建SpringBoot