有权图的最短路径算法

目录

单源最短路径问题

Dijkstra算法

原理 ​

获得最短路径长度的Dijkstra代码实现

时间复杂度

算法优化

优先队列优化后的代码实现

时间复杂度

可以具体获得最短路径的Dijkstra代码实现 

Bellman-Ford算法

原理

代码实现 

Floyed算法

原理

代码实现 


单源最短路径问题

我们的起始点是固定点,从起始点出发到达其他各顶点的最短路径。

Dijkstra算法

此算法不能处理负权边,由于大量的应用不依赖负权边,所以这个算法有非常广泛的应用。

原理 

获得最短路径长度的Dijkstra代码实现

import java.util.Arrays;public class Dijkstra {private WeightedGraph G;private int s;//源点sprivate int[] dis;//整型数组表示源点s到某个顶点的距离private boolean[] visited;//找到还没确定最短距离的顶点public Dijkstra(WeightedGraph G, int s){this.G = G;G.validateVertex(s);//验证合法性this.s = s;dis = new int[G.V()];Arrays.fill(dis, Integer.MAX_VALUE);//赋初值dis[s] = 0;//赋初值为0visited = new boolean[G.V()];while(true){//循环的第一轮找到的必是源点sint cur = -1;//最小的dis值对应的顶点是谁 int curdis = Integer.MAX_VALUE;//当前找到的最小的dis值for(int v = 0; v < G.V(); v ++)if(!visited[v] && dis[v] < curdis){curdis = dis[v];cur = v;}if(cur == -1) break;//代表当前所有的顶点都访问过了,可以退出咯visited[cur] = true;//哪些顶点的dis值已经求出来了for(int w: G.adj(cur))if(!visited[w]){if(dis[cur] + G.getWeight(cur, w) < dis[w])dis[w] = dis[cur] + G.getWeight(cur, w);}}}public boolean isConnectedTo(int v){//判断顶点和源点的连通性G.validateVertex(v);return visited[v];}public int distTo(int v){//从源点s到顶点v对应的最短路径的长度G.validateVertex(v);return dis[v];}static public void main(String[] args){WeightedGraph g = new WeightedGraph("g.txt");Dijkstra dij = new Dijkstra(g, 0);for(int v = 0; v < g.V(); v ++)System.out.print(dij.distTo(v) + " ");System.out.println();}
}

时间复杂度

算法优化

我们可以用优先队列获得v这个顶点对应的dis值,不再是v这个顶点序号的最小值了。我们的优先队列取出来的是顶点的序号,但比较起来是比较的dis值。

优先队列优化后的代码实现

import java.util.Arrays;
import java.util.PriorityQueue;public class Dijkstra {private WeightedGraph G;private int s;private int[] dis;private boolean[] visited;private class Node implements Comparable<Node>{public int v, dis;public Node(int v, int dis){this.v = v;this.dis = dis;}@Overridepublic int compareTo(Node another){return dis - another.dis;}}public Dijkstra(WeightedGraph G, int s){this.G = G;G.validateVertex(s);this.s = s;dis = new int[G.V()];Arrays.fill(dis, Integer.MAX_VALUE);dis[s] = 0;visited = new boolean[G.V()];PriorityQueue<Node> pq = new PriorityQueue<Node>();pq.add(new Node(s, 0));while(!pq.isEmpty()){int cur = pq.remove().v;if(visited[cur]) continue;visited[cur] = true;for(int w: G.adj(cur))if(!visited[w]){if(dis[cur] + G.getWeight(cur, w) < dis[w]){dis[w] = dis[cur] + G.getWeight(cur, w);pq.add(new Node(w, dis[w]));}}}}public boolean isConnectedTo(int v){G.validateVertex(v);return visited[v];}public int distTo(int v){G.validateVertex(v);return dis[v];}static public void main(String[] args){WeightedGraph g = new WeightedGraph("g.txt");Dijkstra dij = new Dijkstra(g, 0);for(int v = 0; v < g.V(); v ++)System.out.print(dij.distTo(v) + " ");System.out.println();}
}

时间复杂度

可以具体获得最短路径的Dijkstra代码实现 

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.PriorityQueue;public class Dijkstra {private WeightedGraph G;private int s;private int[] dis;private boolean[] visited;private int[] pre;private class Node implements Comparable<Node>{public int v, dis;public Node(int v, int dis){this.v = v;this.dis = dis;}@Overridepublic int compareTo(Node another){return dis - another.dis;}}public Dijkstra(WeightedGraph G, int s){this.G = G;G.validateVertex(s);this.s = s;dis = new int[G.V()];Arrays.fill(dis, Integer.MAX_VALUE);pre = new int[G.V()];Arrays.fill(pre, -1);dis[s] = 0;pre[s] = s;visited = new boolean[G.V()];PriorityQueue<Node> pq = new PriorityQueue<Node>();pq.add(new Node(s, 0));while(!pq.isEmpty()){int cur = pq.remove().v;if(visited[cur]) continue;visited[cur] = true;for(int w: G.adj(cur))if(!visited[w]){if(dis[cur] + G.getWeight(cur, w) < dis[w]){dis[w] = dis[cur] + G.getWeight(cur, w);pq.add(new Node(w, dis[w]));pre[w] = cur;}}}}public boolean isConnectedTo(int v){G.validateVertex(v);return visited[v];}public int distTo(int v){G.validateVertex(v);return dis[v];}public Iterable<Integer> path(int t){ArrayList<Integer> res = new ArrayList<>();if(!isConnectedTo(t)) return res;int cur = t;while(cur != s){res.add(cur);cur = pre[cur];}res.add(s);Collections.reverse(res);return res;}static public void main(String[] args){WeightedGraph g = new WeightedGraph("g.txt");Dijkstra dij = new Dijkstra(g, 0);for(int v = 0; v < g.V(); v ++)System.out.print(dij.distTo(v) + " ");System.out.println();System.out.println(dij.path(3));}
}

Bellman-Ford算法

原理

松弛操作有方向性,相当于拐个弯到达某个端点是不是比直接到达某个端点更近。此算法在有向图无向图也成立。

 

代码实现 

import java.util.Arrays;public class BellmanFord {private WeightedGraph G;private int s;private int[] dis;private boolean hasNegCycle = false;public BellmanFord(WeightedGraph G, int s){this.G = G;G.validateVertex(s);this.s = s;dis = new int[G.V()];Arrays.fill(dis, Integer.MAX_VALUE);dis[s] = 0;for(int pass = 1; pass < G.V(); pass ++){for(int v = 0; v < G.V(); v ++)for(int w: G.adj(v))if(dis[v] != Integer.MAX_VALUE &&dis[v] + G.getWeight(v, w) < dis[w])dis[w] = dis[v] + G.getWeight(v, w);}for(int v = 0; v < G.V(); v ++)for(int w : G.adj(v))if(dis[v] != Integer.MAX_VALUE &&dis[v] + G.getWeight(v, w) < dis[w])hasNegCycle = true;}public boolean hasNegativeCycle(){return hasNegCycle;}public boolean isConnectedTo(int v){G.validateVertex(v);return dis[v] != Integer.MAX_VALUE;}public int distTo(int v){G.validateVertex(v);if(hasNegCycle) throw new RuntimeException("exist negative cycle.");return dis[v];}static public void main(String[] args){WeightedGraph g = new WeightedGraph("g.txt");BellmanFord bf = new BellmanFord(g, 0);if(!bf.hasNegativeCycle()){for(int v = 0; v < g.V(); v ++)System.out.print(bf.distTo(v) + " ");System.out.println();}elseSystem.out.println("exist negative cycle.");WeightedGraph g2 = new WeightedGraph("g2.txt");BellmanFord bf2 = new BellmanFord(g2, 0);if(!bf2.hasNegativeCycle()){for(int v = 0; v < g2.V(); v ++)System.out.print(bf2.distTo(v) + " ");System.out.println();}elseSystem.out.println("exist negative cycle.");}
}

Floyed算法

原理

可以包含负权边,也可以包含负权环。 

代码实现 

import java.util.Arrays;public class Floyed {private WeightedGraph G;private int[][] dis;private boolean hasNegCycle = false;public Floyed(WeightedGraph G){this.G = G;dis = new int[G.V()][G.V()];for(int v = 0; v < G.V(); v ++)Arrays.fill(dis[v], Integer.MAX_VALUE);for(int v = 0; v < G.V(); v ++){dis[v][v] = 0;for(int w: G.adj(v))dis[v][w] = G.getWeight(v, w);}for(int t = 0; t < G.V(); t ++)for(int v = 0; v < G.V(); v ++)for(int w = 0; w < G.V(); w ++)if(dis[v][t] != Integer.MAX_VALUE && dis[t][w] != Integer.MAX_VALUE&& dis[v][t] + dis[t][w] < dis[v][w])dis[v][w] = dis[v][t] + dis[t][w];for(int v = 0; v < G.V(); v ++)if(dis[v][v] < 0)hasNegCycle = true;}public boolean hasNegativeCycle(){return hasNegCycle;}public boolean isConnectedTo(int v, int w){G.validateVertex(v);G.validateVertex(w);return dis[v][w] != Integer.MAX_VALUE;}public int distTo(int v, int w){G.validateVertex(v);G.validateVertex(w);return dis[v][w];}static public void main(String[] args){WeightedGraph g = new WeightedGraph("g.txt");Floyed floyed = new Floyed(g);if(!floyed.hasNegativeCycle()){for(int v = 0; v < g.V(); v ++){for(int w = 0; w < g.V(); w ++)System.out.print(floyed.distTo(v, w) + " ");System.out.println();}}elseSystem.out.println("exist negative cycle.");WeightedGraph g2 = new WeightedGraph("g2.txt");Floyed floyed2 = new Floyed(g2);if(!floyed2.hasNegativeCycle()){for(int v = 0; v < g.V(); v ++){for(int w = 0; w < g.V(); w ++)System.out.print(floyed2.distTo(v, w) + " ");System.out.println();}}elseSystem.out.println("exist negative cycle.");}
}

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

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

相关文章

YouTube宣布要求披露AI生成的内容并添加标签

不知道大家在逛YouTube的时候有没有刷到过一些画面和人物看起来不太自然的视频。 没错&#xff0c;这些视频里面的画面和人物可能都是由AI生成的。 近日&#xff0c;YouTube 产品管理副总裁在官方博客文章上表示&#xff1a;生成式 AI 有潜力在 YouTube 上激发创造力&#xff…

IBNR详解及基于R的计算逻辑

一、什么是IBNR IBNR是英文“Incurred But Not Reported”的缩写&#xff0c;中文意思是“已发生未报案未决赔款准备金”。它通常用在保险和金融领域&#xff0c;描述的是非寿险保险事故已经发生&#xff0c;但尚未向保险公司提出索赔的赔案而提取的准备金。 二、IBNR的提取流…

11:kotlin 类和对象 -- 普通类

前面粗咯的讲了类&#xff0c;这篇详细介绍类及相关的概念 定义类使用关键字class class Person { /*...*/ }类声明由类名、类头&#xff08;指定其类型参数、主构造函数等&#xff09;和由{}包围的类体组成。类头和类体都是可选的&#xff1b;如果类没有体&#xff0c;可以省…

vue.draggable拖拽——岗位切换如何判断?

有一个业务场景&#xff1a;把一个单位的某个岗位的人&#xff0c;从某某市A岗位调离出来后&#xff0c;又拖拽回去&#xff0c;如果是回到某某市A岗位&#xff0c;则没有变化&#xff0c;若是换了岗位&#xff0c;则会把色块变成红色&#xff0c;表示岗位的变化。 方法一&…

Maven 介绍

文章目录 什么是 maven为什么要选择mavenmaven 仓库什么是maven中央仓库什么是maven本地仓库 idea如何创建出maven项目如何引入第三方库依赖配置国内源 下载 Maven Helper 插件查看各个项目之间的依赖关系 什么是 maven Maven是 Apache 下的一个纯 Java 开发的开源项目&#x…

DDD 系统间的七种关系梳理与实践

系统间的七种关系 本节将根据耦合度从高到低逐一探讨这些关系。耦合度高有时并不是坏事&#xff0c;它能够让团队内部的系统更加内聚&#xff0c;而不是无法整合的碎块。我们应该根据具体情况进行选择。 因为系统间关系往往也是组织架构的反映&#xff0c;此处每种关系除了描…

超卓航科聚国内外专家学者,共推冷喷涂技术的发展与应用

11月24日——26日&#xff0c;冷喷涂技术及其在增材制造中的应用专题会在襄阳召开&#xff0c;来自国内外200多名科技工作者齐聚一堂&#xff0c;共同交流冷喷涂技术的研究与应用。 本次专题研讨会由中国机械工程学会表面工程分会主办&#xff0c;湖北超卓航空科技股份有限公司…

【EasyExcel实践】导出多个sheet到多个excel文件,并压缩到一个zip文件

文章目录 前言正文一、项目依赖二、封装表格实体和Sheet实体2.1 表格实体2.2 Sheet实体 三、核心实现3.1 核心实现之导出为输出流3.2 web导出3.3 导出为字节数组 四、调试4.1 构建调试用的实体类4.2 控制器调用4.3 测试结果 五、注册大数转换器&#xff0c;长度大于15时&#x…

webGL开发虚拟实验室

开发虚拟实验室是一个具有挑战性但也非常有趣和有价值的任务。通过 WebGL&#xff0c;你可以创建交互式、沉浸式的虚拟实验室&#xff0c;使用户能够进行实验和学习。以下是一些步骤和关键考虑因素&#xff0c;帮助你开始开发虚拟实验室&#xff0c;希望对大家有所帮助。北京木…

Unity 通过代码控制Texture进行缩放

在实际应用开发中&#xff0c;有时候需要通过代码对Texture进行缩放。 有两个方法&#xff0c;一个是通过控制宽高进行缩放&#xff0c;另一个是通过比例值进行等比例缩放。 1、控制宽高的方法&#xff1a; /// <summary>/// 纹理缩放方法一&#xff0c;指定宽高/// &…

游戏开发原画的设计方法

游戏原画设计是游戏开发中至关重要的一环&#xff0c;因为它直接影响到游戏的视觉吸引力和用户体验。以下是一些常见的游戏原画设计方法&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 理解游戏概念&…

如何在Python中操作Redis数据库

目录 一、安装redis-py库 二、连接Redis数据库 三、执行操作 1、设置和获取键值对 2、删除键值对 3、获取列表数据 四、处理数据 1、使用哈希表&#xff08;Hash&#xff09;处理关联数据 2、使用列表&#xff08;List&#xff09;处理有序数据 3、使用集合&#xff…

XIAO ESP32S3之AI应用

一、XIAO ESP32S3 AI应用示例 包含 ChatGPT语音助手、关键字识别等 英文:https://wiki.seeedstudio.com/xiao_esp32s3_speech2chatgpt/ 中文:SenseCraft 模型助手部署 | Seeed Studio Wiki 二、XIAO开发板TinyML项目展示 各种XIAO开发板基于Tiny ML的演示项目:XIAO 系列教…

链接共享平台LinkStack

什么是 LinkStack &#xff1f; LinkStack 是一个独特的平台&#xff0c;为在线管理和共享链接提供了高效的解决方案。平台提供了一个类似于 Linktree 的网站&#xff0c;它可以让用户克服社交媒体平台上只能添加一个链接的限制。借助 LinkStack&#xff0c;用户可以轻松链接到…

Jetson AGX XAVIER刷机时提示invalid_request - Authorization flow not allowed

我下的版本是sdkmanager_1.9.2-10899_amd64.deb&#xff0c;安装后后直接在terminal输入 sdkmanager&#xff0c;出来后提示登录有问题&#xff0c;跳到浏览器链接 http://localhost:8080/?error_descriptionAuthorizationflownotallowed&statehttp://localhost:41369&a…

shell_exec 和 exec区别

shell_exec 和 exec 都是用于在 PHP 中执行系统命令的函数&#xff0c;但它们之间有一些区别。 返回值类型&#xff1a;shell_exec 函数返回命令的输出结果作为字符串&#xff0c;而 exec 函数将输出结果存储在数组中。 输出结果&#xff1a;shell_exec 函数返回命令的完整输出…

录音模块:WT588FM01高性能录音语音芯片IC,功能丰富,音质卓越,满足多样化需求

在音频市场日益繁荣的今天&#xff0c;用户对于录音模块的需求也日益多样化。唯创知音针对这一市场趋势&#xff0c;推出了高性能录音语音芯片模块WT588FM01。凭借其远距离录音、优质音质以及多样化的功能&#xff0c;它成为了众多电子产品中的首选之一。 WT588FM01是深圳唯创…

8 有损压缩的.jpg图片文件格式详解,解封装拆包

有损压缩的.jpg文件 作者将狼才鲸创建日期2023-11-28 1&#xff09;简述 JPEG文件描述 JPEG协议格式分为JPEG、渐进式JPEG&#xff08;图片先显示一部分再显示全部&#xff09;、JPEG2000&#xff08;压缩品质更好&#xff0c;压缩率更高&#xff09;压缩模式&#xff1a;顺序…

苹果mac屏幕投屏镜像工具AirServer2024

airserver 是什么软件&#xff1f;AirServer 是一款 Airplay Mac屏幕镜像应用&#xff0c;AirServer可以通过 mac 实时接收iPhone、iPad以及Android设备的实时屏幕画面。AirServer 可以将一个简单的大屏幕或投影仪变成一个通用的屏幕镜像接收器。在您的大屏幕上启用 AirServer …

Databend 开源周报第 121 期

Databend 是一款现代云数仓。专为弹性和高效设计&#xff0c;为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务&#xff1a;https://app.databend.cn 。 Whats On In Databend 探索 Databend 本周新进展&#xff0c;遇到更贴近你心意的 Databend 。 支持追加流 Da…