Dijkstra算法解析

Dijkstra算法,用于求解图中从一个起点到其他所有节点的最短路径。解决单源最短路径问题的有效方法。

条件

有向

带权路径

时间复杂度 O(n平方)

方法步骤

1 把图上的点分为两个集合 要求的起点 和除了起点之外的点 。能直达的写上权值 不能直达的写上无穷 自己到自己的距离是0

2 在除起点以外的中找权值最小的顶点,这个顶点加入起点所在的集合。由于新顶点的并入,可以把新顶点作为中转点,再重新计算起点到所有除已经并入顶点的距离,找最小的继续并入,直到所有顶点并入起点所在的集合。

以下是对代码的详细解析和注释:

代码解析

全局变量定义
#define N 1005 // 定义最大顶点数为1005
int n, m; // n表示顶点数,m表示边数
bool str[N]; // 用于标记是否已确定最短路径
int dis[N]; // 存储从起始点到各个顶点的最短距离
int g[N][N]; // 邻接矩阵,存储图的结构
  • N:定义图中最大顶点数为1005。

  • nm:分别表示图中的顶点数和边数。

  • str:布尔数组,用于标记某个顶点是否已经确定了最短路径。

  • dis:数组,存储从起点到每个顶点的最短距离。

  • g:邻接矩阵,g[i][j] 表示从顶点 i 到顶点 j 的距离。

Dijkstra算法实现
void dijkstra() {// 初始化dis数组为一个很大的值(这里选择0x3f3f3f3f)memset(dis, 0x3f3f3f3f, sizeof(dis));// 起始点到自身的距离为0dis[1] = 0;for (int i = 1; i <= n; ++i) {int temp = -1; // 选择未确定的顶点// 寻找当前未确定的最小距离顶点for (int j = 1; j <= n; ++j)if (!str[j] && (temp == -1 || dis[j] < dis[temp]))temp = j;// 更新与该顶点相邻的其他顶点的距离for (int j = 1; j <= n; ++j)dis[j] = min(dis[j], dis[temp] + g[temp][j]);// 标记该顶点已经确定了最短路径str[temp] = true;}// 输出结果for (int i = 1; i <= n; ++i) {if (dis[i] == 0x3f3f3f3f)cout << "-1" << " "; // 如果没有到该顶点的路径则输出-1elsecout << dis[i] << " "; // 否则输出最短距离}
}
  1. 初始化

    • memset(dis, 0x3f3f3f3f, sizeof(dis));:将 dis 数组初始化为一个很大的值(0x3f3f3f3f),表示初始时从起点到其他顶点的距离是无穷大。

    • dis[1] = 0;:将起点到自身的距离设置为0。

  2. 主循环

    • for (int i = 1; i <= n; ++i):循环 n 次,每次找到一个未确定最短路径的顶点。

    • int temp = -1;:初始化当前未确定的最短距离顶点为 -1。

    • for (int j = 1; j <= n; ++j):遍历所有顶点,找到未确定最短路径的顶点中距离最短的顶点 temp

      • if (!str[j] && (temp == -1 || dis[j] < dis[temp])):如果顶点 j 未确定最短路径且距离更短,则更新 temp

    • for (int j = 1; j <= n; ++j):更新与顶点 temp 相邻的其他顶点的距离。

      • dis[j] = min(dis[j], dis[temp] + g[temp][j]);:如果通过 temp 到达 j 的距离更短,则更新 dis[j]

    • str[temp] = true;:标记顶点 temp 已经确定了最短路径。

  3. 结果输出

    • 遍历 dis 数组,输出从起点到每个顶点的最短距离。

    • 如果 dis[i] 仍然是 0x3f3f3f3f,表示没有路径到达顶点 i,输出 -1

    • 否则输出 dis[i]

主函数
int main() {// 初始化邻接矩阵g为一个很大的值memset(g, 0x3f3f3f3f, sizeof(g));// 输入顶点数n和边数mcin >> n >> m;while (m--) { // 处理每一条边的输入int x, y, z;cin >> x >> y >> z;// 更新邻接矩阵g中的权值g[x][y] = min(g[x][y], z);}// 调用dijkstra函数求解dijkstra();return 0;
}
  1. 初始化邻接矩阵

    • memset(g, 0x3f3f3f3f, sizeof(g));:将邻接矩阵 g 初始化为一个很大的值(0x3f3f3f3f),表示初始时图中没有边。

  2. 输入图的边

    • cin >> n >> m;:读取顶点数 n 和边数 m

    • while (m--):循环 m 次,读取每一条边的信息。

      • cin >> x >> y >> z;:读取边的起点 x、终点 y 和权重 z

      • g[x][y] = min(g[x][y], z);:更新邻接矩阵 g 中的权值,如果有多条边连接同一对顶点,只保留权重最小的那条边。

  3. 调用Dijkstra算法

    • dijkstra();:调用 dijkstra 函数求解最短路径。

  4. 输出结果

    • dijkstra 函数会输出从起点到每个顶点的最短距离。

示例输入和输出

示例输入
5 7
1 2 4
1 3 3
2 4 2
3 2 1
3 4 5
4 5 1
2 5 7
示例输出

0 2 3 4 5

解释
  • 顶点 1 到顶点 2 的最短距离为 2(1 -> 3 -> 2)。

  • 顶点 1 到顶点 3 的最短距离为 3(1 -> 3)。

  • 顶点 1 到顶点 4 的最短距离为 4(1 -> 3 -> 2 -> 4)。

  • 顶点 1 到顶点 5 的最短距离为 5(1 -> 3 -> 2 -> 4 -> 5)。

关键点总结

  1. 邻接矩阵:使用二维数组 g[N][N] 表示图的结构,g[i][j] 表示从顶点 i 到顶点 j 的距离。

  2. 选择最短距离顶点:通过遍历所有顶点,找到未确定最短路径的顶点中距离最短的顶点。

  3. 更新邻接顶点的距离:通过当前顶点更新其邻接顶点的距离。

  4. 标记顶点:使用布尔数组 str 标记顶点是否已经确定了最短路径。

Dijkstra算法详细步骤解析

1. 初始化

在算法开始之前,需要进行以下初始化操作:

  1. 初始化距离数组 dis

    • dis 数组中的所有元素初始化为一个很大的值(如 0x3f3f3f3f),表示从起点到其他顶点的距离初始为无穷大。

    • 将起点的距离设置为 0,即 dis[start] = 0

  2. 初始化访问标记数组 str

    • str 数组中的所有元素初始化为 false,表示所有顶点初始时都未被访问过。

  3. 初始化邻接矩阵 g

    • 将邻接矩阵 g 中的所有元素初始化为一个很大的值(如 0x3f3f3f3f),表示初始时图中没有边。

2. 主循环

Dijkstra算法的核心是一个主循环,该循环执行 n 次(n 为顶点数),每次找到一个未访问的最短距离顶点,并更新其邻接顶点的距离。

  1. 选择未访问的最短距离顶点

    • 遍历所有顶点,找到未访问的顶点中距离最短的顶点 u

    • 如果所有顶点都已被访问过,或者没有找到未访问的顶点,则退出循环。

  2. 更新邻接顶点的距离

    • 遍历顶点 u 的所有邻接顶点 v,如果通过 u 到达 v 的距离更短,则更新 dis[v]

    • 具体来说,如果 dis[u] + g[u][v] < dis[v],则更新 dis[v] = dis[u] + g[u][v]

  3. 标记顶点为已访问

    • 将顶点 u 标记为已访问,即 str[u] = true,避免重复处理。

3. 结果输出

在主循环结束后,dis 数组中存储了从起点到每个顶点的最短距离。遍历 dis 数组,输出结果:

  • 如果 dis[i] 仍然是初始的大值(如 0x3f3f3f3f),表示没有路径到达顶点 i,输出 -1

  • 否则,输出 dis[i],表示从起点到顶点 i 的最短距离。

示例执行过程

假设图的结构如下:

  • 顶点数 n = 5

  • 边数 m = 7

  • 边的权重如下:

    • 1 -> 2: 4

    • 1 -> 3: 3

    • 2 -> 4: 2

    • 3 -> 2: 1

    • 3 -> 4: 5

    • 4 -> 5: 1

    • 2 -> 5: 7

初始化
  • dis 数组:[0, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f]

  • str 数组:[false, false, false, false, false]

  • g 邻接矩阵:

    [[0x3f3f3f3f, 4, 3, 0x3f3f3f3f, 0x3f3f3f3f],[0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 2, 0x3f3f3f3f],[0x3f3f3f3f, 1, 0x3f3f3f3f, 5, 0x3f3f3f3f],[0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 1],[0x3f3f3f3f, 7, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f]
    ]
第1次循环
  1. 选择未访问的最短距离顶点

    • 遍历所有顶点,找到未访问的顶点中距离最短的顶点 u = 1(起点)。

  2. 更新邻接顶点的距离

    • 遍历顶点 1 的邻接顶点 23

      • dis[2] = min(dis[2], dis[1] + g[1][2]) = min(0x3f3f3f3f, 0 + 4) = 4

      • dis[3] = min(dis[3], dis[1] + g[1][3]) = min(0x3f3f3f3f, 0 + 3) = 3

  3. 标记顶点为已访问

    • str[1] = true

第2次循环
  1. 选择未访问的最短距离顶点

    • 遍历所有顶点,找到未访问的顶点中距离最短的顶点 u = 3dis[3] = 3)。

  2. 更新邻接顶点的距离

    • 遍历顶点 3 的邻接顶点 24

      • dis[2] = min(dis[2], dis[3] + g[3][2]) = min(4, 3 + 1) = 4

      • dis[4] = min(dis[4], dis[3] + g[3][4]) = min(0x3f3f3f3f, 3 + 5) = 8

  3. 标记顶点为已访问

    • str[3] = true

第3次循环
  1. 选择未访问的最短距离顶点

    • 遍历所有顶点,找到未访问的顶点中距离最短的顶点 u = 2dis[2] = 4)。

  2. 更新邻接顶点的距离

    • 遍历顶点 2 的邻接顶点 45

      • dis[4] = min(dis[4], dis[2] + g[2][4]) = min(8, 4 + 2) = 6

      • dis[5] = min(dis[5], dis[2] + g[2][5]) = min(0x3f3f3f3f, 4 + 7) = 11

  3. 标记顶点为已访问

    • str[2] = true

第4次循环
  1. 选择未访问的最短距离顶点

    • 遍历所有顶点,找到未访问的顶点中距离最短的顶点 u = 4dis[4] = 6)。

  2. 更新邻接顶点的距离

    • 遍历顶点 4 的邻接顶点 5

      • dis[5] = min(dis[5], dis[4] + g[4][5]) = min(11, 6 + 1) = 7

  3. 标记顶点为已访问

    • str[4] = true

第5次循环
  1. 选择未访问的最短距离顶点

    • 遍历所有顶点,找到未访问的顶点中距离最短的顶点 u = 5dis[5] = 7)。

  2. 更新邻接顶点的距离

    • 顶点 5 没有邻接顶点,无需更新。

  3. 标记顶点为已访问

    • str[5] = true

结果输出

遍历 dis 数组,输出从起点到每个顶点的最短距离:

  • dis[1] = 0

  • dis[2] = 4

  • dis[3] = 3

  • dis[4] = 6

  • dis[5] = 7

关键点总结

  1. 选择未访问的最短距离顶点

    • 每次选择未访问的顶点中距离最短的顶点,确保每一步都选择当前最优的顶点进行处理。

  2. 更新邻接顶点的距离

    • 通过当前顶点更新其邻接顶点的距离,确保每一步都更新到最新的最短距离。

  3. 标记顶点为已访问

    • 避免重复处理已访问的顶点,提高算法的效率。

  4. 结果输出

    • 最终输出从起点到每个顶点的最短距离,如果没有路径到达某个顶点,则输出 -1

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

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

相关文章

【深度学习】DeepSeek模型介绍与部署

原文链接&#xff1a;DeepSeek-V3 1. 介绍 DeepSeek-V3&#xff0c;一个强大的混合专家 (MoE) 语言模型&#xff0c;拥有 671B 总参数&#xff0c;其中每个 token 激活 37B 参数。 为了实现高效推理和成本效益的训练&#xff0c;DeepSeek-V3 采用了多头潜在注意力 (MLA) 和 De…

深度学习深度解析:从基础到前沿

引言 深度学习作为人工智能的一个重要分支&#xff0c;通过模拟人脑的神经网络结构来进行数据分析和模式识别。它在图像识别、自然语言处理、语音识别等领域取得了显著成果。本文将深入探讨深度学习的基础知识、主要模型架构以及当前的研究热点和发展趋势。 基础概念与数学原理…

如何实现滑动列表功能

文章目录 1 概念介绍2 使用方法3 示例代码 我们在上一章回中介绍了沉浸式状态栏相关的内容&#xff0c;本章回中将介绍SliverList组件.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1 概念介绍 我们在这里介绍的SliverList组件是一种列表类组件&#xff0c;类似我们之前介…

OpenEuler学习笔记(十七):OpenEuler搭建Redis高可用生产环境

在OpenEuler上搭建Redis高可用生产环境&#xff0c;通常可以采用Redis Sentinel或Redis Cluster两种方式&#xff0c;以下分别介绍两种方式的搭建步骤&#xff1a; 基于Redis Sentinel的高可用环境搭建 安装Redis 配置软件源&#xff1a;可以使用OpenEuler的默认软件源&#…

前沿课题推荐:提升水下导航精度的多源数据融合与算法研究

随着海洋探测技术的迅猛发展&#xff0c;水下地形匹配导航逐渐成为国际研究的热点领域。在全球范围内&#xff0c;水下导航技术的精确性对于科学探索、资源勘探及国防安全等方面都至关重要。我国在这一领域的研究与应用需求日益增长&#xff0c;亟需通过先进的技术手段提升水下…

[创业之路-269]:《创业讨论会》- 系统之韵:从麻雀到5G系统的共通性探索

关键词&#xff1a; 从系统的角度&#xff0c;麻雀、人体系统、企业系统、软硬件系统、软件系统、通信系统、5G系统是类似的&#xff1a; 都有&#xff1a;内在看不见的规律、外在显性各种现象 都是&#xff1a;输入、处理、输出 都是&#xff1a;静态、要素、组成、结构、组织…

【疑问】固态硬盘也是以扇区作为单位吗

回答 固态硬盘&#xff08;SSD&#xff09;与传统机械硬盘&#xff08;HDD&#xff09;在存储结构技术不一样。 理由 机械硬盘使用旋转的磁盘和磁头来读写数据&#xff0c;所以有扇区、磁道和柱面等概念 而固态硬盘则使用闪存芯片来存储数据、没有机械部件&#xff0c;固态硬盘…

浅析CDN安全策略防范

CDN&#xff08;内容分发网络&#xff09;信息安全策略是保障内容分发网络在提供高效服务的同时&#xff0c;确保数据传输安全、防止恶意攻击和保护用户隐私的重要手段。以下从多个方面详细介绍CDN的信息安全策略&#xff1a; 1. 数据加密 数据加密是CDN信息安全策略的核心之…

three.js+WebGL踩坑经验合集(6.1):负缩放,负定矩阵和行列式的关系(2D版本)

春节忙完一轮&#xff0c;总算可以继续来写博客了。希望在春节假期结束之前能多更新几篇。 这一篇会偏理论多一点。笔者本没打算在这一系列里面重点讲理论&#xff0c;所以像相机矩阵推导这种网上已经很多优质文章的内容&#xff0c;笔者就一笔带过。 然而关于负缩放&#xf…

【华为OD-E卷 - 报数游戏 100分(python、java、c++、js、c)】

【华为OD-E卷 - 报数游戏 100分&#xff08;python、java、c、js、c&#xff09;】 题目 100个人围成一圈&#xff0c;每个人有一个编码&#xff0c;编号从1开始到100。 他们从1开始依次报数&#xff0c;报到为M的人自动退出圈圈&#xff0c;然后下一个人接着从1开始报数&…

Linux抢占式内核:技术演进与源码解析

一、引言 Linux内核作为全球广泛使用的开源操作系统核心,其设计和实现一直是计算机科学领域的研究热点。从早期的非抢占式内核到2.6版本引入的抢占式内核,Linux在实时性和响应能力上取得了显著进步。本文将深入探讨Linux抢占式内核的引入背景、技术实现以及与非抢占式内核的…

HTB:Administrator[WriteUP]

目录 连接至HTB服务器并启动靶机 信息收集 使用rustscan对靶机TCP端口进行开放扫描 将靶机TCP开放端口号提取并保存 使用nmap对靶机TCP开放端口进行脚本、服务扫描 使用nmap对靶机TCP开放端口进行漏洞、系统扫描 使用nmap对靶机常用UDP端口进行开放扫描 使用nmap对靶机…

DeepSeek模型与OpenAI模型原理和技术架构的异同分析

DeepSeek模型与OpenAI模型原理和技术架构的异同分析 一、模型原理 &#xff08;一&#xff09;DeepSeek R1 DeepSeek R1的核心原理是基于强化学习&#xff08;RL&#xff09;的训练方式&#xff0c;其创新之处在于不依赖任何监督微调&#xff08;SFT&#xff09;数据&#x…

一文讲解JVM中的G1垃圾收集器

接上一篇博文&#xff0c;这篇博文讲下JVM中的G1垃圾收集器 G1在JDK1.7时引入&#xff0c;在JDK9时取代了CMS成为默认的垃圾收集器&#xff1b; G1把Java堆划分为多个大小相等的独立区域Region&#xff0c;每个区域都可以扮演新生代&#xff08;Eden和Survivor&#xff09;或老…

力扣第149场双周赛

文章目录 题目总览题目详解找到字符串中合法的相邻数字重新安排会议得到最多空余时间I3440.重新安排会议得到最多空余时间II 第149场双周赛 题目总览 找到字符串中合法的相邻数字 重新安排会议得到最多空余时间I 重新安排会议得到最多空余时间II 变成好标题的最少代价 题目…

25届 信息安全领域毕业设计选题88例:前沿课题

目录 前言 毕设选题 开题指导建议 更多精选选题 选题帮助 最后 前言 大家好,这里是海浪学长毕设专题! 大四是整个大学期间最忙碌的时光&#xff0c;一边要忙着准备考研、考公、考教资或者实习为毕业后面临的升学就业做准备,一边要为毕业设计耗费大量精力。学长给大家整理…

【Vite + Vue + Ts 项目三个 tsconfig 文件】

Vite Vue Ts 项目三个 tsconfig 文件 为什么 Vite Vue Ts 项目会有三个 tsconfig 文件&#xff1f;首先我们先了解什么是 tsconfig.json ? 为什么 Vite Vue Ts 项目会有三个 tsconfig 文件&#xff1f; 在使用 Vite 创建 vue-ts 模板的项目时&#xff0c;会发现除了 ts…

【RAG】SKLearnVectorStore 避免使用gpt4all会connection err

gpt4all 列表中包含了多个开源的大模型,如 Qwen2.5、Llama 3、DeepSeek、Mistral 等,但 不包含 OpenAI 的 GPT-4o。GPT-4o 是 OpenAI 提供的闭源模型,目前只能通过 OpenAI API 或 ChatGPT 官方应用(网页版、移动端)访问,并不支持本地运行,也没有 GGUF 量化格式的模型文件…

【算法设计与分析】实验6:n皇后问题的回溯法设计与求解

目录 一、实验目的 二、实验环境 三、实验内容 四、核心代码 五、记录与处理 六、思考与总结 七、完整报告和成果文件提取链接 一、实验目的 针对n皇后问题开展分析、建模、评价&#xff0c;算法设计与优化&#xff0c;并进行编码实践。 掌握回溯法求解问题的思想&#…

【算法】回溯算法专题① ——子集型回溯 python

目录 引入变形实战演练总结 引入 子集 https://leetcode.cn/problems/subsets/description/ 给你一个整数数组 nums &#xff0c;数组中的元素 互不相同 。返回该数组所有可能的子集&#xff08;幂集&#xff09;。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 …