(算法基础)朴素版的Dijkstra算法

news/2024/11/17 22:46:06/

适用情景

  1. 在最短路问题当中的单源最短路(一号点到其他所有点之间的距离)的只有正权边的情况。


时间复杂度

  1. O(N^2)


算法解释(朴素版的Dijkstra)

  1. 首先是关于这个图的存储,图的话主要是分为稠密图与稀疏图。稠密图就是说n的平方与m是一个量级的,对于稠密图的话,用邻接矩阵来存;稀疏图的话是n与m为一个量级的,对与稀疏图的话,就用邻接表来存。在这边我先举一个用邻接矩阵存图为例子吧。

int g[N][N];
  1. 然后这个邻接矩阵等会儿我是要把具体的边的信息放进去的,所以在一开始有必要进行一些预处理初始化,在最短路问题当中有两类特殊情况:这就是重边,一个就是自环,由于当下背景是最短路,对于重边而言的话,只需要取小的就可以;然后对于自环而言的话,不能是负环(不然最短路就变成负无穷了),然后对于正环而言的话,在最短路里相当于没有,所以就这样初始化

for (int i=1;i<=n;i++)
{for (int j=1;j<=n;j++){if (i==j){g[i][j]=0;}else{g[i][j]=0x3f3f3f3f;  //为等会儿输入边权重取小做准备}}
}
  1. 然后还需要开两个数组,一个数组就是用来记录一下该点是不是已经确定了最短路距离,还有一个数组用来记录一下每点到一号点之间的最短路距离是多少,一开始的话每点初始化为正无穷(当然,一号点除外,它到他自己本身的距离就是0

int st[N];
int dist[N];
memset(dist,0x3f3f3f3f,sizeof(dist));
dist[1]=0;
  1. 然后往邻接矩阵里面输入每一条边的有关信息.

while(m--)
{int a,b,c;scanf("%d %d %d",&a,&b,&c);g[a][b]=MIN(g[a][b],c);
}
  1. 然后就进入了迪杰斯特拉算法的精髓:首先要去找到这么一个点1. 还没有被正式确认下来最短路距离,2. 到1号点的距离比其他与他一样的同胞(还没有被正式确认最短路距离)到一号点的距离都要短(因此逃不开还要遍历一遍所有点)。先把这个点去找到,这个点找到之后,去遍历一下这个点所能连接到的其他点,看一看能不能更新那些点的最短路距离。遍历一圈完成之后,这个点的最短路距离也就正式被确定下来然后依次往复,不断循环。显而易见,每一次循环确定下来一个点的最短路距离,既然有n个点,那么就需要n次循环

for (int i=0;i<n;i++)
{int t=0;for (int j=1;j<=n;j++){if (st[j]==0 && (t==0 || dist[j]<dist[t])){t=j;}}st[t]=1;for (int j=1;j<=n;j++){dist[j]=MIN(dist[j],dist[t]+g[t][j]);}
}
  1. 然后由于迪杰斯特拉算法的要求,就是说所有的边都必须是正权边,因此如果说从一号点走不到n号点的话,那么n号点的距离dist应该还是保持初始化的那个值0x3f3f3f3f,在当前情形是不存在负权边,这个初始化的正无穷大值不会被略微更新小

if (dist[n]==0x3f3f3f3f)
{printf("%d\n",-1);
}
else
{printf("%d\n",dist[n]);
}

例题

来源:AcWing

849. Dijkstra求最短路 I - AcWing题库

#include <stdio.h>
#include <string.h>
#define N 510
#define MIN(a,b) ((a)<(b)?(a):(b))
int g[N][N];
int st[N];
int dist[N];
int main()
{memset(dist,0x3f3f3f3f,sizeof(dist));dist[1]=0;int n,m;scanf("%d %d",&n,&m);for (int i=1;i<=n;i++){for (int j=1;j<=n;j++){if (i==j){g[i][j]=0;}else{g[i][j]=0x3f3f3f3f;  //为等会儿输入边权重取小做准备}}}while(m--){int a,b,c;scanf("%d %d %d",&a,&b,&c);g[a][b]=MIN(g[a][b],c);}for (int i=0;i<n;i++){int t=0;for (int j=1;j<=n;j++){if (st[j]==0 && (t==0 || dist[j]<dist[t])){t=j;}}st[t]=1;for (int j=1;j<=n;j++){dist[j]=MIN(dist[j],dist[t]+g[t][j]);}}if (dist[n]==0x3f3f3f3f){printf("%d\n",-1);}else{printf("%d\n",dist[n]);}return 0;
}

http://www.ppmy.cn/news/35153.html

相关文章

C++分析以下关于指针的操作有什么问题

代码一:按值传递/按引用传递 按值传递是指,在函数调用时,将参数的值复制一份传递给函数,函数中对参数值的修改不会影响到原始值 对于指针类型的参数,在按值传递的情况下,传递给函数的是指针变量的值(即指针变量所存储的地址),而不是指针所指向的内存地址。因此,当在…

一文看懂数据仓库

数据仓库数据仓库的概念数据仓库的主要特征数据仓库的分层数据仓库的分层介绍原始数据层&#xff1a;ODS&#xff08;Operational Data Store&#xff09;数据仓库层&#xff1a;DW&#xff08;Data Warehouse&#xff09;数据明细层&#xff1a;DWD&#xff08;Data Warehouse…

进阶C语言——字符函数和字符串函数【详解】(二)

文章目录1. strtok2. strerror3. memcpy4. memmove5. memcmp6. memset1. strtok sep参数是个字符串&#xff0c;定义了用作分隔符的字符集合第一个参数指定一个字符串&#xff0c;它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记strtok函数找到str中的下一个标记…

算法训练:贪心与回溯

目录 1.手套&#xff08;贪心算法&#xff09; 2.字符串通配符&#xff08;回溯算法&#xff09; 1.手套 题目描述&#xff1a; 在地下室里放着n种颜色的手套&#xff0c;手套分左右手&#xff0c;但是每种颜色的左右手手套个数不一定相同。A先生现在要出门&#xff0c;所以…

【redis】redis缓存更新策略

目录一、缓存更新策略二、主动更新策略三、Cache Aside Pattern3.1 删除缓存还是更新缓存?3.2 如何保证缓存与数据库的操作同时成功或失败&#xff1f;3.3 先操作缓存还是先操作数据库3.3.1 先删缓存再删库3.3.2 先删库再删缓存一、缓存更新策略 1.内存淘汰&#xff1a;不用自…

Flutter-Scaffold组件

在Flutter开发当中&#xff0c;我们可能会遇到以下的需求&#xff1a;实现页面组合使用&#xff0c;比如说有悬浮按钮、顶部菜单栏、左右抽屉侧边栏、底部导航栏等等效果。Scaffold组件可以帮我们实现上面需求说的效果。这篇博客主要分享容器组件的Scaffold组件的使用&#xff…

【数据结构篇C++实现】- 堆

文章目录&#x1f680;一、堆的原理精讲⛳&#xff08;一&#xff09;堆的概念⛳&#xff08;二&#xff09;看图识最大堆⛳&#xff08;三&#xff09;详解堆是用数组表示的树&#x1f680;二、堆的向下调整算法&#x1f680;三、堆的向上调整算法&#x1f680;四、将任意一棵…

古茗科技面试:为什么 ElasticSearch 更适合复杂条件搜索?

文章目录 ElasticSearch 简介倒排索引联合索引查询跳表合并策略Bitset 合并策略MySQL 最多使用一个条件涉及的索引来过滤,然后剩余的条件只能在遍历行过程中进行内存过滤。 上述这种处理复杂条件查询的方式因为只能通过一个索引进行过滤,所以需要进行大量的 I/O 操作来读取行…