图论算法(三)--最短路径 的Bellman-Flod [ 带负权值图 ] 的解法(JAVA )

Bellman-Flod算法

对于带有负权值的图,我们已经不能通过Dijkstra算法进行求解了
原因:Dijkstra每次都会找一个距源点(设为s)最近的点,然后将该距离定为这个点到源点的最短路径;如果一个顶点u被加入了book[i])( book[i] == 1 说明这个s到u的路径权值已被记录,不可再更改),但是如果存在v到u的权值为负,那么s经v到u到值要更小。
例如:
Dijkstra
如果用Dijkstra跑只能得到2这个结果,但实际结果应该是1才对
s—->u 2
s—->v—-> 1


为解决带负权值的问题,这里需要用到Bellman-Flod算法
问题描述:有如下带负权值的图,求从1号点到其他各点的最短路径长度

city
Input:
5 5
2 3 2
1 2 -3
1 5 5
4 5 2
3 4 3

Output:
0 -3 -1 2 4

import java.util.Scanner;
public class minPath {static int[] u = new int[10];static int[] v = new int[10];static int[] w = new int[10];static int[] dis = new int[10];static int n, m;static Scanner input  = new Scanner(System.in);public static void main(String[] args) {n = input.nextInt();m = input.nextInt();for (int i = 1; i <= m; i++) {u[i] = input.nextInt();v[i] = input.nextInt();w[i] = input.nextInt();}for (int i = 1; i <= n; i++) {dis[i] = 99999999;}dis[1] = 0;bellmanFlod();for (int i = 1; i <= n; i++) {System.out.print(dis[i] + " ");}}private static void bellmanFlod() {/*** 由离散数学的理论得出,在一个n个顶点的图中,任意两点之间的最短路径最多包含n-1条边* */for (int i = 1; i <= n - 1; i++) {for (int j = 1; j <= m; j++) {if (dis[v[j]] > dis[u[j]] + w[j]) {dis[v[j]] = dis[u[j]] + w[j];}}}}
}

时间复杂度:O(NM)

算法优化

优化版本一

优化原因:在实际操作中,很多时候不会进行n-1次,毕竟不是每个点都会达到n-1条边的情况的,因此当不在能更新之后,我们就可以终止程序了,即使现在还没进行到第n-1阶段。

优化方法:添加一个一维数组备份来dis,如果新一轮的松弛中数组没有发生变化,则可以提前跳出循环。

import java.util.Scanner;public class minPath {static int[] u = new int[10];static int[] v = new int[10];static int[] w = new int[10];static int[] dis = new int[10];static int[] bak = new int[10];static int n, m;static int check, flag;static Scanner input  = new Scanner(System.in);public static void main(String[] args) {n = input.nextInt();m = input.nextInt();for (int i = 1; i <= m; i++) {u[i] = input.nextInt();v[i] = input.nextInt();w[i] = input.nextInt();}for (int i = 1; i <= n; i++) {dis[i] = 99999999;}dis[1] = 0;bellmanFlod();if (flag == 1) {System.out.println("此图含有负权回路");} else {for (int j = 1; j <= n; j++) {System.out.print(dis[j] + " ");}}}private static void bellmanFlod() {/*** 由离散数学的理论得出,在一个n个顶点的图中,任意两点之间的最短路径最多包含n-1条边* */for (int i = 1; i <= n - 1; i++) {bak[i] = dis[i];for (int j = 1; j <= m; j++) {if (dis[v[j]] > dis[u[j]] + w[j]) {dis[v[j]] = dis[u[j]] + w[j];}}/*** 检测dis是否还在变化* */check = 0;for (int j = 1; j <= n; j++) {if (bak[i] != dis[i]) {check = 1;break;}if (check == 0) {break;}}/*** 检测负权回路* 原理:最短路径所包含的边做多为n-1条,在进行n-1次松弛之后如果还能继续松弛成功,* 那说明此图必定含有负权回路* */flag = 0;for (int j = 1; j <= m; j++) {if (dis[v[i]] > dis[u[i]] + w[i]) {flag = 1;}}}}
}

优化原因:因为最短路径做多有n-1条边,所以Bellman-Ford算法做多有n-1个阶段。而每个阶段都要对每条边进行“松弛操作”,使得“估计值”变为“确定值”。而对于本阶段来说,上个阶段松弛完的结果是不会再改变的,而原算法每个阶段都会重新计算,浪费时间。

优化方法:每次仅对最短路“估计值”变化为“确定值”的顶点的所有出边执行松弛操作,可以采用队列进行优化
时间复杂度:O(NM)

import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;public class minPath {static int[] u = new int[8];static int[] v = new int[8];static int[] w = new int[8];/*** first 要比 n 的值大1* next  要比 m 的值大1* */static int[] first = new int[6];static int[] next = new int[8];static int[] dis = new int[6];static int[] book = new int[6];static int n, m;static Queue<Integer> queue = new LinkedList<>();static Scanner input = new Scanner(System.in);public static void main(String[] args) {n = input.nextInt();m = input.nextInt();for (int i = 1; i <= n; i++) {dis[i] = 99999999;}dis[1] = 0;for (int i = 1; i <= n; i++) {first[i] = -1;}for (int i = 1; i <= m; i++) {u[i] = input.nextInt();v[i] = input.nextInt();w[i] = input.nextInt();/*** 建立邻接表的关键语句!!!* */next[i] = first[u[i]];first[u[i]] = i;}queue.offer(1);book[1] = 1;bellomanFlodPlus();for (int i = 1; i <= n; i++) {System.out.print(dis[i] + " ");}}private static void bellomanFlodPlus() {while (!queue.isEmpty()) {/*** 当前的队首元素* */int k = first[queue.peek()];while (k != -1) {if (dis[v[k]] > dis[u[k]] + w[k]) {dis[v[k]] = dis[u[k]] + w[k];/*** 用数组来判断v[k]是否已经在队列中* 不使用数组进行记录的话,要迭代队列,十分不方便* */if(book[v[k]] == 0) {queue.offer(v[k]);book[v[k]] = 1;}}k = next[k];}book[queue.peek()] = 0;queue.remove();}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/569827.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringCloud介绍(一)

1.1 SpringCloud介绍 1.1.1 微服务架构演化 简而言之&#xff0c;微服务就是开发一组小型服务的方式来开发一个独立的应用系统&#xff0c;每个小型服务都运行在自己的进程中&#xff0c;并采用HTTP资源API轻量级的机制来互相通信。这些服务围绕业务功能进行构建&…

最短路径问题总结,时间复杂度,空间复杂度对比(JAVA)

最短路径问题总结 图中还有些地方没有完善&#xff0c;但是一时也没没办法解决&#xff0c;希望大家知道的能够提供一下表中不足的地方&#xff0c;万分感谢&#xff01;&#xff01;&#xff01; 最短路径算法&#xff08;一&#xff09;–DFS/BFS求解&#xff08;JAVA &…

树--树的基本性质(JAVA)

前几篇文章介绍了图的搜索算法&#xff0c;最短路径算法&#xff0c;接下来介绍树&#xff1a; 树和图 树实际上就是不含回路的无向连通图 虽然树不连通&#xff0c;没有回路了&#xff0c;但是这也使得树这种数据结构有了更多的特性&#xff1a; 1.一棵树中的任意两个结点…

看后端程序员调试CORS的姿势

# 目录 为什么有同源策略&#xff1f; 需要解决的问题CORS跨域请求方案 preflightwithCredentials附&#xff1a;高效、优雅地调试CORS实现为什么有同源策略&#xff1f; 同源策略Same Origin Policy 是一种约定&#xff0c;是浏览器最核心的安全功能&#xff1a;该策略允许在…

图论算法(四)--最小生成树的Kruskal [ 加边 ] 、Prim [ 加点 ] 的解法(JAVA)

之前我们介绍了求最短路径算法&#xff0c;现在又讲最小生成树算法&#xff0c;这两个算法有什么区别呢&#xff1f; 首先要明确&#xff0c;最短路径和最小生成树是两个不同的概念。 最短路径是对于一个图的两个结点而言的。在一个图中&#xff0c;结点A通过某些结点和边可以…

express+handlebars 快速搭建网站前后台

最近在重构公司网站&#xff0c;原来网站使用PHP&#xff0c;前后端不分离&#xff0c;添加与更新网站内容仍使用原始方法&#xff0c;先出布局再把调好的布局给PHP后端开发&#xff0c;花时间长&#xff0c;维护不易。因此决定将网站前后端分离&#xff0c;核心功能含网站下单…

定义一个二维数组并输入数据,将二维数组元素的值按升序排列,并输出排序后的二维数组。

目录 问题&#xff1a; 回顾&#xff1a; 给出两种做法&#xff1a; 解法一&#xff1a;调用qsort 函数进行排序 代码&#xff1a; 运行结果&#xff1a; 解法二&#xff1a;冒泡排序 代码&#xff1a; 运行结果: 回顾里的4种方法的模板参考&#xff1a; 1.冒泡排序…

第五届省赛(软件类)真题----Java大学C组答案及解析

第五届省赛&#xff08;软件类&#xff09;真题—-Java大学C组答案及解析 杨辉三角调和级数回文素数过大年位平方和单位分数n级台阶 一、杨辉三角 二项式的系数规律&#xff0c;我国数学家很早就发现了。 如【图1.png】&#xff0c;我国南宋数学家杨辉1261年所著的《详解九…

Angular4.x 安装|创建项目|目录结构|创建组件

Angular4.x 安装|创建项目|目录结构|创建组件 安装最新版本的 nodejs node.js 官网&#xff1a;https://nodejs.org/zh-cn/ 去官网下载 node.js&#xff0c;下一步下一步就可以了。只要 node.js 安装成功&#xff0c;那么 npm 也会帮你安装完成&#xff01; 注意&#xff1a;请…

第五届省赛(软件类)真题----Java大学B组答案及解析

第五届省赛&#xff08;软件类&#xff09;真题—-Java大学B组答案及解析 正则切分调和级数n的n次幂七对数字勾股定理九阶数独G将军 一、正则切分 java中提供了对正则表达式的支持。 有的时候&#xff0c;恰当地使用正则&#xff0c;可以让我们的工作事半功倍&#xff01; …

第五届省赛(软件类)真题----Java大学A组答案及解析

第五届省赛&#xff08;软件类&#xff09;真题—-Java大学A组答案及解析 子序列最大长度莱布尼茨公式n的n次幂七对数字勾股定理九阶数独矩阵射线 一、子序列最大长度 一个串的子串是指该串的一个连续的局部。如果不要求连续&#xff0c;则可称为它的子序列。 比如对串&…

第六届省赛(软件类)真题----Java大学C组答案及解析

第六届省赛&#xff08;软件类&#xff09;真题----Java大学C组答案及解析隔行变色立方尾无穷分数循环节长度格子中输出奇妙的数字加法变乘法移动距离打印大X垒骰子 一、隔行变色 Excel表的格子很多&#xff0c;为了避免把某行的数据和相邻行混淆&#xff0c;可以采用隔行变色的…

spring_01概念及案例

1.什么是IOC?   IOC概念:inverse of Controll,控制反转,所谓控制反转,就是把创建对象和维护对象关系的权利从程序中转移到spring的容器中(applicationContext.xml),而程序本身不再维护 2.什么是di? dependency injection,依赖注入,di和IOC是一个概念,spring的设计者认为di等…

斐波那契数列(二)--矩阵优化算法

之前写了一篇从斐波那契数列分析递归与动态规划&#xff08;JAVA&#xff09;来优化斐波那契数列&#xff0c;这样可以使算法的时间复杂度从O(n^2)变到O(n),这是使用递归公式f(n)f(n-1)f(n-2)求斐波那契数列的最优算法&#xff0c;但是这只是一维世界下的极限。下面我们将其从一…

第六届省赛(软件类)真题----Java大学B组答案及解析

第六届省赛&#xff08;软件类&#xff09;真题----Java大学B组答案及解析三角形面积立方变自身三羊献瑞循环节长度九数组分数加法变乘法牌型种数饮料换购垒骰子生命之树 一、三角形面积如【图1】所示。图中的所有小方格面积都是1。那么&#xff0c;图中的三角形面积应该是多少…

【学习总结】GirlsInAI ML-diary day-11-while循环

【学习总结】GirlsInAI ML-diary 总 原博github链接-day11 认识while循环执行 对于while/break/continue的认识 新值替换变量 一般while语句 无限循环 & break continue 作业 1-更新变量 这一条没什么新的东西&#xff0c;别的语言也一样&#xff1a;python在赋值时&#x…

@PathVariable、@RequestParam、@RequestBody注解

讲解更加详细的参考资料 https://blog.csdn.net/u011410529/article/details/66974974 https://www.cnblogs.com/soul-wonder/p/8920553.html PathVariable注解的作用&#xff0c;获取请求地址中传递的参数&#xff0c;即&#xff1a;从URL模版中取值。 RequestParam 是从reque…

深入浅出讲算法思想--蛮力法思想分析及应用

蛮力法&#xff08;brute force method&#xff0c;也称为穷举法或枚举法&#xff09;是一种简单直接地解决问题的方法&#xff0c;常常直接基于问题的描述&#xff0c;所以&#xff0c;蛮力法也是最容易应用的方法。虽然&#xff0c;用蛮力法设计的算法时间特性往往也是最低的…

光耦在短距离通信中的应用

在高低压隔离系统设计中&#xff0c;难免会使用光耦来通信。在选择光耦器件时&#xff0c;需要考虑光耦允许的最大通信速率&#xff0c;否则在高速通信时会失败. 对于高速的光耦应用时&#xff0c;需要注意电流传输比率和开关速度。 参考文档《Basic Characteristics and Appli…

从NetCore报错到MySql安全

从NetCore报错到MySql安全 原文:从NetCore报错到MySql安全之前项目在测试服务器上的一些接口时不时会报出下面的错误&#xff1a;&#xff08;采用Abp框架&#xff09; "SocketException: 你的主机中的软件中止了一个已建立的连接。 STACK TRACE: at MySqlConnector.Pr…