当前位置: 首页 > news >正文

图论14-最短路径-Dijkstra算法+Bellman-Ford算法+Floyed算法

文章目录

  • 0 代码仓库
  • 1 Dijkstra算法
  • 2 Dijkstra算法的实现
    • 2.1 设置距离数组
    • 2.2 找到当前路径的最小值 curdis,及对应的该顶点cur
    • 2.3 更新权重
    • 2.4 其他接口
      • 2.4.1 判断某个顶点的连通性
      • 2.4.2 求源点s到某个顶点的最短路径
  • 3使用优先队列优化-Dijkstra算法
    • 3.1 设计内部类node
    • 3.2 入队
    • 3.3 记录路径
    • 3.4 整体
  • 4 Bellman-Ford算法
    • 4.1 松弛操作
    • 4.2 负权环
    • 4.3 算法思想
    • 4.4 进行V-1次松弛操作
    • 4.5 判断负权环
    • 4.6 整体
  • 5 Floyed算法
    • 5.1 设置记录两点最短距离的数组,并初始化两点之间的距离
    • 5.2 更新两点之间的距离

0 代码仓库

https://github.com/Chufeng-Jiang/Graph-Theory/tree/main/src/Chapter11_Min_Path

1 Dijkstra算法

在这里插入图片描述

2 Dijkstra算法的实现

2.1 设置距离数组

//用于存储从源点到当前节点的距离,并初始化
dis = new int[G.V()];
Arrays.fill(dis, Integer.MAX_VALUE);
dis[s] = 0;

2.2 找到当前路径的最小值 curdis,及对应的该顶点cur

int cur = -1, curdis = Integer.MAX_VALUE;for(int v = 0; v < G.V(); v ++)if(!visited[v] && dis[v] < curdis){curdis = dis[v];cur = v;}

2.3 更新权重

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);}

2.4 其他接口

2.4.1 判断某个顶点的连通性

public boolean isConnectedTo(int v){G.validateVertex(v);return visited[v];
}

2.4.2 求源点s到某个顶点的最短路径

public int distTo(int v){G.validateVertex(v);return dis[v];
}

在这里插入图片描述

3使用优先队列优化-Dijkstra算法

3.1 设计内部类node

存放节点编号和距离

    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;}}

3.2 入队

PriorityQueue<Node> pq = new PriorityQueue<Node>();pq.add(new Node(s, 0));

这里的缺点就是,更新node时候,会重复添加节点相同的node,但是路径值不一样。不影响最后结果。

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;}}
}

3.3 记录路径

private int[] pre;
  • 更新pre数组
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 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;}

3.4 整体

package Chapter11_Min_Path.Dijkstra_pq;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));}
}

4 Bellman-Ford算法

4.1 松弛操作

在这里插入图片描述

4.2 负权环

在这里插入图片描述

4.3 算法思想

在这里插入图片描述

4.4 进行V-1次松弛操作

// 进行V-1次松弛操作
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);pre[w] = v;}
}

4.5 判断负权环

// 多进行一次操作,如果还有更新,那么存在负权换
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;

4.6 整体

package Chapter11_Min_Path.BellmanFord;import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;public class BellmanFord {private WeightedGraph G;private int s;private int[] dis;private int[] pre;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;pre = new int[G.V()];Arrays.fill(pre, -1);// 进行V-1次松弛操作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);pre[w] = v;}}// 多进行一次操作,如果还有更新,那么存在负权换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];}public Iterable<Integer> path(int t){ArrayList<Integer> res = new ArrayList<Integer>();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("gw2.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();System.out.println(bf.path(3));}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.");}
}

5 Floyed算法

在这里插入图片描述

5.1 设置记录两点最短距离的数组,并初始化两点之间的距离

private int[][] dis;
  • 初始化两点之间的距离
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);
}

5.2 更新两点之间的距离

第一重循环:测试两点之间经过点t是否存在更短的路径。

        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];

在这里插入图片描述
在这里插入图片描述

相关文章:

图论14-最短路径-Dijkstra算法+Bellman-Ford算法+Floyed算法

文章目录 0 代码仓库1 Dijkstra算法2 Dijkstra算法的实现2.1 设置距离数组2.2 找到当前路径的最小值 curdis&#xff0c;及对应的该顶点cur2.3 更新权重2.4 其他接口2.4.1 判断某个顶点的连通性2.4.2 求源点s到某个顶点的最短路径 3使用优先队列优化-Dijkstra算法3.1 设计内部类…...

OpenCV 实现透视变换

一&#xff1a;OpenCV透视变换的概念 仿射变换(affine transform)与透视变换(perspective transform)在图像还原、图像局部变化处理方面有重要意义。通常&#xff0c;在2D平面中&#xff0c;仿射变换的应用较多&#xff0c;而在3D平面中&#xff0c;透视变换又有了自己的一席之…...

ChinaSoft 论坛巡礼|开源软件供应链论坛

2023年CCF中国软件大会&#xff08;CCF ChinaSoft 2023&#xff09;由CCF主办&#xff0c;CCF系统软件专委会、形式化方法专委会、软件工程专委会以及复旦大学联合承办&#xff0c;将于2023年12月1-3日在上海国际会议中心举行。 本次大会主题是“智能化软件创新推动数字经济与社…...

VUE 组合式API

响应式 data 选项式API_响应式 <template><h3>选项式API</h3><p>{{ message }}</p> </template> <script> export default {data(){return{message:"选项式API 绑定数据"}} } </script>组合式API_响应式 <…...

尝试使用php给pdf添加水印

在开发中增加pdf水印的功能是很常见的&#xff0c;经过实验发现这中间还是会有很多问题的。第一种模式&#xff0c;采用生成图片的方式把需要添加的内容保存成图片&#xff0c;再将图片加到pdf中间&#xff0c;这种方法略麻烦一些&#xff0c;不过可以解决中文乱码的问题&#…...

ubuntu上安装edge浏览器

1下载edge浏览器 官网下载 edge浏览器的linux版本可在上面的官网中寻找。 我选择的是Linux(.deb)。 2 安装 可在终端的edge安装包所在的路径下输入下面命令安装。 sudo dpkg -i edge安装包的名称.deb3 安装可能存在的问题 1dpkg:依赖关系问题使得edge-stable的配置工作不…...

动态切换 Spring Boot 打包配置:使用 Maven Profiles 管理 JAR 和 WAR

引言 在多环境开发中&#xff0c;我们经常需要根据部署环境来改变 Spring Boot 应用的打包方式。本文将探讨如何使用 Maven Profiles 结合依赖排除来动态地切换 JAR 和 WAR 打包配置。 1. 修改 pom.xml 以支持 WAR 包 转换 Spring Boot 应用从 JAR 到 WAR 时&#xff0c;首先…...

微信小程序使用阿里巴巴矢量图标

一&#xff0c;介绍 微信小程序使用图标有两种方式&#xff0c;一种是在线获取&#xff0c;一种是下载到本地使用&#xff0c; 第一种在线获取的有个缺点就是图标是灰色的&#xff0c;不能显示彩色图标&#xff0c;而且第一种是每次请求资源的&#xff0c;虽然很快&#xff0…...

使用JAVA pdf转word

使用spire.pdf 非常简单。 查看 https://mvnrepository.com/artifact/e-iceblue/spire.pdf 注意&#xff0c;这个包在 e-iceblue 下。 下面开始撸代码 先来pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://mav…...

成都瀚网科技有限公司抖音带货的正规

成都瀚网科技有限公司&#xff0c;一家在科技领域有着深厚积累的公司&#xff0c;近年来也开始涉足电子商务领域&#xff0c;特别是在抖音等短视频平台上进行带货活动。在这个充满机遇与挑战的时代&#xff0c;该公司以其独特的商业模式和运营策略&#xff0c;正在赢得消费者的…...

windows服务器热备、负载均衡配置

安装网络负载平衡 需要加入的服务器上全部需要安装网络负载平衡管理器 图形化安装&#xff1a;使用服务器管理器安装 在服务器管理器中&#xff0c;使用“添加角色和功能”向导添加网络负载均衡功能。 完成向导后&#xff0c;将安装 NLB&#xff0c;并且不需要重启计算机。 …...

samba服务器搭建 挂载远程目录 常用配置参数介绍

samba 直接复用linux的用户&#xff0c;但是Linux 用户的密码和 smbpasswd 设置的密码是分开的。 Linux 用户的密码是存储在 Linux 系统的用户数据库中&#xff0c;通常是 /etc/shadow 文件中以加密形式存储的。Samba 用户的密码是存储在专门的 Samba 密码数据库中 smbpasswd…...

Ansible命令使用

ansible ansible的命令 ansible命令模块Pingcommand 模块shell 模块copy 模块file 模块fetch 模块cron 模块yum 模块service 模块user 模块group 模块script 模块setup 模块get_url模块stat模块unarchive模块unarchive模块 ansible的命令 /usr/bin/ansible  Ansibe AD-Hoc 临…...

element 周选择器el-date-picker

2023.11.13今天我学习了在使用element 周选择器的时候&#xff0c;我们会发现默认的时间选择为星期日到下一个星期一&#xff0c;如图&#xff1a; 我们需要改成显示星期一到星期天&#xff0c;只需要加一行代码&#xff1a;picker-options <el-date-pickertype"week&…...

No200.精选前端面试题,享受每天的挑战和学习

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…...

前端面试之事件循环

什么是事件循环 首先&#xff0c; JavaScript是一门单线程的语言&#xff0c;意味着同一时间内只能做一件事&#xff0c;这并不意味着单线程就是阻塞&#xff0c;而是实现单线程非阻塞的方法就是事件循环 在JavaScript中&#xff0c;所欲任务都可以分为&#xff1a; 同步任务…...

sass 封装媒体查询工具

背景 以往写媒体查询可能是这样的&#xff1a; .header {display: flex;width: 100%; }media (width > 320px) and (width < 480px) {.header {height: 50px;} }media (width > 480px) and (width < 768px) {.header {height: 60px;} }media (width > 768px) …...

眼科动态图像处理系统使用说明(2023-8-11 ccc)

眼科动态图像处理系统使用说明 2023-8-11 ccc 动态眼科图像捕捉存贮分析与传输系统&#xff0c;是由计算机软件工程师和医学专家组结合&#xff0c;为满足医院临床工作的需要&#xff0c;在2000年开发的专门用于各类眼科图像自动化分析、处理和传输的软件系统。该系统可以和各…...

国际阿里云:提高CDN缓存命中率教程!!!

CDN缓存命中率低会导致源站压力大&#xff0c;静态资源访问效率低。您可以根据导致CDN缓存命中率低的具体原因&#xff0c;选择对应的优化策略来提高CDN的缓存命中率。 背景信息 CDN通过将静态资源缓存在CDN节点上实现资源访问加速。当客户端访问某资源时&#xff0c;如果CDN节…...

关于“谈谈你对 ES 的理解”

普通人 它是一个基于 Apache Lucene 开源的一个分布式搜索引擎框架。 一般用它来做 ● 日志记录和分析 ● 公共数据采集 ● 全文检索 ● 数据可视化分析等等 高手 Elasticsearch &#xff0c;简称 ES 。它是建立在全文搜索引擎库 Apache Lucene 基础之上的一个开源的搜索…...

新谈设计模式 Chapter 05 — 原型模式 Prototype

Chapter 05 — 原型模式 Prototype灵魂速记&#xff1a;复印机——照着原件复制一份&#xff0c;省得从头再造。秒懂类比 你有一份精心排版的简历模板。每次投不同公司&#xff0c;你不是从头写一份新的&#xff0c;而是复印一份&#xff0c;改几个字。 原型模式就是这个"…...

2026网盘风云再起:告别“传不动”,这两款不限速良心网盘实测解析

近些年&#xff0c;网盘市场经历了一轮又一轮的洗牌。从早年各大云盘陆续关停&#xff0c;到后来现有网盘部分服务全面转向收费模式&#xff0c;甚至对非会员进行严苛的网速阉割。用户常常面临「存不下、传不动、下不来」的窘境。 如今已是2026年&#xff0c;网盘市场看似被少…...

美元、日元、欧元怎么选?外汇新手该从哪个货币对开始?

最近有不少刚接触外汇交易的朋友问我同一个问题&#xff1a;美元、日元、欧元这些主流货币到底该怎么选&#xff1f;作为一个过来人&#xff0c;我想说的是——选对起步品种&#xff0c;比你想象中重要得多。 很多新手一上来就想着“赚快钱”&#xff0c;直接冲进波动剧烈的交叉…...

3步永久保存青春记忆:GetQzonehistory让QQ空间数据永不消逝

3步永久保存青春记忆&#xff1a;GetQzonehistory让QQ空间数据永不消逝 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 你的数字回忆正在流失吗&#xff1f; 每天有超过10万条QQ空间动…...

3种突破Cursor Pro限制的创新方案:解锁AI编程全功能体验

3种突破Cursor Pro限制的创新方案&#xff1a;解锁AI编程全功能体验 【免费下载链接】cursor-free-vip [Support 0.45]&#xff08;Multi Language 多语言&#xff09;自动注册 Cursor Ai &#xff0c;自动重置机器ID &#xff0c; 免费升级使用Pro 功能: Youve reached your t…...

华硕笔记本性能调校新纪元:GHelper如何重塑硬件控制体验

华硕笔记本性能调校新纪元&#xff1a;GHelper如何重塑硬件控制体验 【免费下载链接】g-helper Lightweight, open-source control tool for ASUS laptops and ROG Ally. Manage performance modes, fans, GPU, battery, and RGB lighting across Zephyrus, Flow, TUF, Strix, …...

Local Moondream2快速部署:VS Code Dev Container一键开发环境

Local Moondream2快速部署&#xff1a;VS Code Dev Container一键开发环境 1. 项目简介 Local Moondream2是一个基于Moondream2构建的超轻量级视觉对话Web界面。它能够让你的电脑拥有"眼睛"&#xff0c;可以对上传的图片进行详细描述、反推绘画提示词&#xff0c;或…...

告别重复劳动,用快马平台ai高效生成openclaw自动化脚本

最近在折腾一些文件批量处理的自动化任务&#xff0c;发现OpenClaw这个命令行工具特别适合做这类工作。但每次都要手动敲命令实在太费时间了&#xff0c;特别是需要组合多个命令的时候&#xff0c;调试起来特别麻烦。后来发现了InsCode(快马)平台&#xff0c;用它来编写OpenCla…...

终极文件伪装指南:如何3分钟让任何文件“隐形“传输

终极文件伪装指南&#xff1a;如何3分钟让任何文件"隐形"传输 【免费下载链接】apate 简洁、快速地对文件进行格式伪装 项目地址: https://gitcode.com/gh_mirrors/apa/apate 在当今数据安全日益重要的时代&#xff0c;apate文件伪装工具为开发者和技术爱好者…...

Speechless:如何用一款免费Chrome插件永久保存你的微博记忆

Speechless&#xff1a;如何用一款免费Chrome插件永久保存你的微博记忆 【免费下载链接】Speechless 把新浪微博的内容&#xff0c;导出成 PDF 文件进行备份的 Chrome Extension。 项目地址: https://gitcode.com/gh_mirrors/sp/Speechless 在数字时代&#xff0c;我们的…...