Dijkstra(迪杰斯特拉)

news/2024/9/22 17:41:25

Dijkstra(迪杰斯特拉)算法

简单版

须知

首先用几个数组表示需要的状态:

  • dis[] 表示距离从初始点到对应点的距离,初始点置为0,其他置为无穷
  • graph[][] 邻接矩阵,记录两点间连线的权重,可以记录无向图和有向图
  • check[] 判断当前点是否被记录

算法思路:

假定a为起点,每次选距离a最近的点然后更新。

image-20240428172502767

image-20240428172924153

先从a到b和c,发现到b的距离最小,锁定dis[b],

再从b到其他点,如图中第二次,发现从b到c为当前状态下最小的,所以记录

不断重复

代码

以https://www.luogu.com.cn/problem/P1339为例,AC代码如下

#define rep(i,j,k) for(i=(j);i<(k);i++)
const int N = 8000 + 10;
int ii, jj;int n, m, s, t;
int u, v, w;
int graph[N][N];//邻接矩阵
int dis[N],check[N];//距离,状态
int main() {cin >> n >> m >> s >> t;//初始化,所有dis为无穷rep(ii, 0, n+1) {dis[ii] = INT_MAX;//graph全为0,表示无连接rep(jj, 0, n+1)graph[ii][jj] = 0;}//初始化,由于无向图,所以graph[u][v],graph[V][u]rep(ii, 0, m) {cin >> u >> v >> w;graph[u][v] = w;graph[v][u] = w;}//起点定为0dis[s] = 0;for (int i = 1; i <= n; i++) {//先遍历所有点,找出最小的int minn = INT_MAX, mini = 0;//该过程,即第i次寻找最小的dis,还要注意不能是已经选过的for (int j = 1; j <= n; j++) if (!check[j] && dis[j] < minn) minn = dis[j], mini = j;//将选中的置为1check[mini] = 1;//枚举邻边//从当前的最小位置向每个点连接,如果可以连接上,与原本的距离作对比for (int j = 1; j <= n; j++) {//从mini 到 i有连线,判断if (graph[mini][j] > 0) {dis[j] = min(dis[j], graph[mini][j] + minn);}}}cout << dis[t] << endl;return 0;
}

堆优化

学习原因

在找到最小距离时,枚举了很多并没有改变的点,额外提高了时间,所以用堆优化,把已经更改的点存入优先队列

之所以用优先队列,我们用距离d数组进行排序,最前面的就是我们要的那个mini。

int minn = INT_MAX, mini = 0;
for (int j = 1; j <= n; j++) if (!check[j] && dis[j] < minn) minn = dis[j], mini = j;

这时可以用一个优先队列来存储每次更新的点和路线长度,详情请参考:https://www.bilibili.com/video/BV1Ya411L7gb/?spm_id_from=333.999.0.0&vd_source=10b3ee1feea99fbdd76960a61a32f71e

具体实现

同样为上面简单版题目的ac代码

typedef pair<int, int> pii;
#define rep(i,j,k) for(i=(j);i<(k);i++)const int N = 8000 + 10;
int ii, jj;int n, m, s, t;
int u, v, w;
int graph[N][N];
int dis[N], check[N];
priority_queue<pii>pq;int main() {cin >> n >> m >> s >> t;rep(ii, 0, n + 1) {dis[ii] = INT_MAX;rep(jj, 0, n + 1)graph[ii][jj] = 0;}rep(ii, 0, m) {cin >> u >> v >> w;graph[u][v] = w;graph[v][u] = w;}dis[s] = 0;//先将起点push进pq中pq.push({ 0,s });while(q.size()){//找到最小的顶点int mini = q.top().second;q.pop();//每次取top,因为此时的top表示的是从起点到达u点的最短长度//那么只需要从最短长度开始遍历其他点,就可以极大地降低时间复杂度if (vis[mini])continue;vis[mini] = 1;rep(j, 1, n + 1) {if (g[mini][j] > 0) {if (d[j] > d[mini] + g[mini][j]) {d[j] = d[mini] + g[mini][j];q.push({ -d[j],j });}}}}cout << dis[t] << endl;return 0;
}

注意:pq默认为大跟堆,如果用小跟堆会麻烦一点,所以将路径长度取-1再存储。路径只起到标识作用,不对结果产生影响。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

Преимущества RS485 для сбора данных LoRaWAN

Сборщик данных RS485 to LoRaWAN — это сборщик данных, который использует стандартный протокол LoRaWAN для беспроводного интерфейса восходящей линии с…

机器学习实践第四篇——贝叶斯分类器

一.什么是贝叶斯分类器1.1贝叶斯定理贝叶斯定理是贝叶斯统计学中的核心定理,它描述了在获得新的观察数据后如何更新概率估计。贝叶斯定理的数学表达如下:$$P(A|B) = \frac{P(B|A) \cdot P(A)}{P(B)}$$其中,$P(A|B)$ 表示在给定观察数据 $B$ 的条件下,事件 $A$ 发生的概率。…

算法-动态规划

原文链接:https://blog.csdn.net/u013309870/article/details/75193592http://t.csdnimg.cn/GgRFt 动态规划算法的核心 理解一个算法就要理解一个算法的核心,动态规划算法的核心是下面的一个小故事。A * "1+1+1+1+1+1+1+1 =?" *A : "上面等式的值是多少"…

[转帖]国产主流数据库存储类型简析

https://blog.csdn.net/solihawk/article/details/137807944国产数据库在技术架构上主要分为集中式、基于中间件分布式和原生分布式架构,衍生出集中式架构和分布式架构。那么在这些部署架构中,从数据分布的视角来看,在数据库中数据分布的形态是怎样的。本文将简要分析OceanB…

第 4篇 Scrum 冲刺博客

这个作业属于哪个课程 软件工程2024这个作业要求在哪里 团队作业4——项目冲刺这个作业的目标 记录敏捷流程下第四天的项目开发进展,对团队昨日的项目进度进行总结一、每日站立式会议 1、每日站立式会议照片2、会议摘要本次会议为第四次Scrum Meeting会议~ 由于本次会议队长召…

数据库升级PostgreSql+Garnet

目录前言PostgreSql安装测试额外Nuget安装Person.cs模拟运行Navicate连postgresql解决方案Garnet为什么要选择Garnet而不是RedisRedis不再开源Windows版的Redis是由微软维护的Windows Redis版本老旧,后续可能不再更新Garnet性能强于Redis安装测试安装可视化工具C# 代码连接测试…

Vue学习知识汇总

官网:https://cn.vuejs.org/ 前置知识:完整的学习vue: html + css、JavaScript、css3、HTML5、第三方库、网络通信、ES6+、webpack、模块化、包管理器、css预编译器 体验vue功能:html + css、JavaScriptVue拥有以下特点:渐进式 组件化 响应式Vue的应用场景:前台的部分页面 中…

玩转创想三维 K1 系列主板之二:编译 MCU 固件,恢复裁剪组件

前言 原创文章,转载引用请务必注明链接,水平有限,如有疏漏,欢迎交流指正。 文章如有更新请访问 DFRobot 社区 及 cnblogs 博客园,前者内容较全,后者排版及阅读体验更佳。 本文是摸索创想三维 K1 系列软硬件系统的一些内容分享。最近创想三维的工作人员联系了我,希望接下…