迪杰斯特拉(Dijkstra)算法(C/C++)

news2024/9/27 19:14:59

迪杰斯特拉(Dijkstra)算法是一种用于在加权图中找到单个源点到所有其他顶点的最短路径的算法。它是由荷兰计算机科学家艾兹格·迪科斯彻(Edsger Dijkstra)在1956年提出的。Dijkstra算法适用于处理带有非负权重的图。迪杰斯特拉算法主要特点是从起始点开始,采用贪心算法,每次遍历到始点距离最近且未访问过的顶点的邻接节点,直到扩展到终点为止。适用的是单源路径最短路问题,对于多源则采用弗洛伊德(Floyd)算法。

基本思想:

1. 创建一个集合S,用于存储已经找到最短路径的顶点。
2. 将所有顶点的最短路径估计值初始化为无穷大(或一个非常大的数),除了源点其值为0。
3. 不断从未加入S的顶点中选择一个具有最小估计值的顶点u,加入到S中。
4. 更新u的所有邻接顶点v的最短路径估计值。如果通过u到达v的路径比当前已知的路径更短,则更新v的估计值。
5. 重复步骤3和4,直到所有顶点都被加入到S中。

Dijkstra算法的时间复杂度为O(n^2)

下面介绍Dijkstra算法最重要的思想,如果A->B的代价为10,A->C的代价为1,C->B的代价为2,那么我们可以采用绕路的方式,把C点当作中转点,路线为ACB,这样代价为3小于A直接到B的代价10。


图解算法:

下面放一张Dijkstra算法的动态实现图,方便大家理解一下Dijkstra算法的主要思想。没有看懂没有关系,下面我会一步一步的详解。图片来自全栈程序员站长。

下面我们将以此图为例子进行一步一步讲解。

初始:

我们初始设有6个点,起点为a,终点为b,每个点到另一个点的距离如图所示,如果不能到达则为inf,Dis数组为起点到任意一点的最短距离,vis为标记数组,每次寻找最短距离。起点到起点不需要任何代价,所以为0,标记为true。

第一步: 

从起点到能够到达的点更新最小距离,与6号点相邻能到达的有1、3、5号点,距离分别为9、2、9,在Dis数组里面都比inf要小,所以更新其值。我们寻找其中最小的距离为2(3号结点),那么我们就更新vis数组标记为true。

第二步:

由3号点可以到达2、4号点,我们发现起点到2号点的距离为2+10=12<inf,所以更新Dis数组,起点到4号点为2+11=13<inf,所以更新Dis数组。此时Dis数组中的最短距离为9,对应5号点。把5号点标记为true。

第三步:

由5号点可以到达4号点,那么由5号点作为中转点,起点到达4号点的距离为9+6=15>13,所以不更新Dis数组,此时Dis数组中最小的为12(2号点),把2号点vis标记为true。

第四步: 

由2号点可以到达4号点,2号点作为中转点,起点到达4号点的距离为2+10+15=27<13,所以Dis数组不更新。此时Dis数组中最小值为13(4号结点),标记vis数组。

 第五步:

此时没有被标记的点且Dis数组中最小的值为1号点,那么标记1号点,1号点可以到达2、3号点,把1号点作为中转点,起点到达2号点的距离为14+7=21<12,不更新,起点到达2号点的距离为14+9=23<2不更新,此时vis数组都标记完成,算法结束,起点到每个点的最小距离为Dis数组。

视频讲解可以看一下这意味B站up主的,博主觉得他讲的非常好,通俗易懂,-->点击直达<-- 


C++实现示例:

#include<iostream>
using namespace std;
int n,e,s;//n个顶点,e条边,s是起点
const int inf=0x7fffff;
int dis[101];//dis[i]起点到i的最短距离
int cheak[101];//标记是否找到
int graph[101][101];//记录路径i->j有路径

int main(){
	for(int i=1;i<=100;i++){//初始无穷大
		dis[i]=inf;
	}
	cin>>n>>e;
	for(int i=1;i<=e;i++){//邻接矩阵存储
		int a,b,c;
		cin>>a>>b>>c;
		graph[a][b]=c;
	}
	cin>>s;
	dis[s]=0;//起点到起点不需要带价
	for(int i=1;i<=n;i++){
		int minn=inf,minx;
		for(int j=1;j<=n;j++){
			if(dis[j]<minn&&cheak[j]==0){//寻找此点到其他点的最小距离
				minn=dis[j];
				minx=j;
			}
		}
		cheak[minx]=1;//标记到达的最小点
		for(int j=1;j<=n;j++){//更新以最小距离点最为中转点的最小距离
			if(graph[minx][j]>0){
				if(minn+graph[minx][j]<dis[j]){
					dis[j]=minn+graph[minx][j];
				}
			}
		}
	}
	for(int i=1;i<=n;i++){//打印最短距离
		cout<<dis[i]<<" ";
	}
	return 0;
}

 算法例题:

Dijkstra算法直接考一般是不会直接考的,都是跟一些其他算法,或者新定义的概念结合起来考,由于Dijkstra算法原理很简单,考察Dijkstra算法更加偏向于其他算法的结合。下面我选取一个例题讲解。

AcWing 4275. Dijkstra序列

Dijkstra 算法是非常著名的贪心算法之一。

它用于解决单源最短路径问题,即指定一个特定源顶点,求该顶点到给定图的所有其他顶点的最短路径。

它由计算机科学家 Edsger W. Dijkstra 于 19561956 年构思并在三年后出版。

在该算法中,我们需要不断维护一个包含最短路径树中顶点的集合。

在每一步中,我们找到一个尚未在集合内且与源顶点距离最小的顶点,并将其收于集合中。

因此,通过 Dijkstra 算法,我们可以逐步生成一个有序的顶点序列,我们称之为 Dijkstra 序列。

对于一个给定的图,可能有多个 Dijkstra 序列。

例如,{5,1,3,4,2} 和 {5,3,1,2,4} 都是给定图的 Dijkstra 序列。

注意,序列中的第一个顶点即为指定的特定源顶点。

你的任务是检查给定的序列是否是 Dijkstra 序列。

输入格式

第一行包含两个整数 N 和 M,表示图中点和边的数量。

点的编号 1∼N。

接下来 M 行,每行包含三个整数 a,b,c,表示点 a 和点 b 之间存在一条无向边,长度为 c。

再一行包含整数 K,表示需要判断的序列个数。

接下来 K 行,每行包含一个 1∼N 的排列,表示一个给定序列。

输出格式

共 K 行,第 i 行输出第 K 个序列的判断,如果序列是 Dijkstra 序列则输出 Yes,否则输出 No

数据范围

1≤N≤1000,
1≤M≤10^5,
1≤a,b≤N,
1≤c≤100,
1≤K≤100,
保证给定无向图是连通图,
保证无重边和自环(官网没提,但是经实测,官网数据符合此条件)。

输入样例:
5 7
1 2 2
1 5 1
2 3 1
2 4 1
2 5 2
3 5 1
3 4 1
4
5 1 3 4 2
5 3 1 2 4
2 3 4 5 1
3 2 1 5 4
输出样例:
Yes
Yes
Yes
No
解题思路:

此题主要是考察了Dijkstra的逆向解决思路。题意是给定一个序列,让判断是否是Dijkstra序列,当然这个题的新概念Dijkstra序列也是很好理解的,上面我们图解算法,每一步都能标记一个点,这就是本题所说的Dijkstra序列,我们的解题思路就是验证即可,唯一不同的就是每一步选取一个最短距离的点,与给定的序列顺序比较是否为一致。判断一致需要看其他点是否被标记过,并且还有没有比此点距离还小的点。如果给定的序列中有任意一个点不满足,那么它就算不是Dijkstra序列,如果都满足,就是Dijkstra序列。

AC代码:
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf=105;
int n,m;
int a[1005];
int g[1005][1005];
bool cheak[1005];
int dis[1005];
bool dij(int x){
	dis[x]=0;//起点到起点初始
	cheak[x]=1;
	for(int i=1;i<=n;i++){//给定序列的n个点进行验证
		int t=a[i];
		cheak[t]=1;//标记此点
		for(int j=1;j<=n;j++){//查看此点是否为最短距离的点
			if(!cheak[j]&&dis[j]<dis[t]){//还有距离更短的点,则不满足
				return false;
			}
		}
		for(int j=1;j<=n;j++){//由此点作为中转点,绕路更新最短距离
			if(dis[t]+g[t][j]<dis[j]&&g[t][j]>0){
				dis[j]=dis[t]+g[t][j];
			}
		}
	}
	return true;
}
int main(){
	cin>>n>>m;
	memset(g,inf,sizeof(g));//初始无穷大,不能到达就是无穷大
	for(int i=1;i<=m;i++){
		int x,y,z;
		cin>>x>>y>>z;
		g[x][y]=g[y][x]=z;//无向边
	}
	cin>>m;
	while(m--){
		memset(cheak,0,sizeof(cheak));//初始化0
		memset(dis,inf,sizeof(dis));
		for(int i=1;i<=n;i++){
			cin>>a[i];
		}
		cout<<(dij(a[1])?"Yes":"No")<<endl;
	}
	return 0;
}

题目不再过多举例,比较难的都是Dijkstra与其他算法的集合,博主将会单独出一篇讲解。下篇更新弗洛伊德(Floyd)算法。执笔至此,感触彼多,全文将至,落笔为终,感谢大家的支持。 

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

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

相关文章

k8s上部署ingress-controller

一、安装helm仓库 # helm pull ingress-nginx/ingress-nginx 二、修改 三、运行 # kubectl label nodes node01.110111.cn ingresstrue# kubectl label nodes node02.110112.cn ingresstrue# helm upgrade --install ingress-nginx -n ingress-nginx . -f values.yaml 四、检…

布局管理(Layouts)-Qt-思维导图-学习笔记

布局管理(Layouts) Qt 提供了非常丰富的布局类&#xff0c;主要包括以下基本布局管理类 QBoxLayout 提供了水平和垂直的布局管理&#xff0c;可以将子部件按行或列排列。根据排列方向的不同&#xff0c;QBoxLayout 分为 QHBoxLayout&#xff08;水平布局&#xff09;和 QVBox…

宏定义———C语言

*符号代表全部的意思*.i代表的是全部的点i文件 宏定义 &#xff1a; 1.定义&#xff1a; #define 宏名 常量功能&#xff1a;宏名代替常量&#xff0c;宏名要求全大写且见名知义 2.示例&#xff1a; #include <stdio.h> #define PI 3.14 #define Q 4 #define P QQi…

Ubuntu系统+宝塔面板部署Frp内网穿透服务

一、搭建目的 上次在局域网中搭建了自己的个人网盘之后&#xff0c;上传文件、照片都很方便&#xff0c;但是只能限制在内网中访问&#xff01;所以这次再搭建一个内网穿透服务器&#xff0c;这样不管在哪里都能访问到家里的云盘&#xff01; 二、内网穿透Frp是什么&#xff1…

连接一切:Web3如何推动物联网的发展

物联网面临的挑战 物联网&#xff08;IoT&#xff09;作为现代科技的重要组成部分&#xff0c;通过将各种智能设备和系统互联&#xff0c;正在以惊人的速度改变我们的生活方式。从智能家居到智慧城市&#xff0c;物联网的应用无处不在。然而&#xff0c;随着设备数量的急剧增加…

华为---端口隔离简介和示例配置

目录 1. 端口隔离概念 2. 端口隔离作用 3. 端口隔离优点 4. 端口隔离缺点 5. 端口隔离的方法和应用场景 6. 端口隔离配置 6.1 端口隔离相关配置命令 6.2 端口隔离配置思路 7. 示例配置 7.1 示例场景 7.2 网络拓扑图 7.3 基本配置 7.4端口隔离配置与验证 7.4.1 双…

初识--树(1)

下面就是这篇博客要讲的内容 树 二叉树堆 树概念及结构二叉树的概念及结构二叉树的实现堆的概念及运用 这篇博客主要以二叉树为主要内容。 1、树的概念及结构 1.1树的概念&#xff1a; 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个有限…

C语言 - 构造类型

构造类型&#xff1a; 数据类型的分类&#xff1a; 基本类型&#xff1a;整数型&#xff1a;短整型&#xff08;short&#xff09;、整型&#xff08;int&#xff09;、长整型&#xff08;long&#xff09;、长长整型&#xff08;long long&#xff09; 浮点型&#xff1a;单…

Java | Leetcode Java题解之第336题回文对

题目&#xff1a; 题解&#xff1a; class Solution {public List<List<Integer>> palindromePairs(String[] words) {List<List<Integer>> ans new ArrayList<>();int n words.length;for (int i 0; i < n; i) {for (int j 0; j < n…

让科技党狂喜的电动车什么样,新日凯迪拉氮,你值得拥有!

这些年电动车企为了创新可以说“八仙过海&#xff0c;各显神通”&#xff0c;有的深挖智能技术开辟新赛道&#xff0c;有的狂卷性能卷出新场景。然而&#xff0c;真正触动消费者心弦的是&#xff1a;如何实实在在地提升骑行体验。正是洞察了这一核心需求&#xff0c;新日电动车…

如何进行屏幕录制?有哪些免费的录屏软件推荐?

如何进行屏幕录制&#xff1f;有哪些免费的录屏软件推荐&#xff1f; 对于内容创作者、教育工作者和游戏玩家来说。精通屏幕录制技术已成为一项不可或缺的技能&#xff01;本文将深入探讨如何使用市面上的顶级屏幕录制软件&#xff0c;例如嗨格式录屏大师和OBS Studio&#xff…

hyper-v安装window10操作系统

Hyper-V是微软的一款虚拟化产品&#xff0c;是微软第一个采用类似Vmware ESXi和Citrix Xen的基于hypervisor的技术。 目标&#xff1a;在window10的物理机上基于hyper-v运行虚拟window10。 准备条件 准备好window10操作系统&#xff0c;iso、wim、esd等都行&#xff0c;我这…

侧向开敞式通风天窗的设计特点和优势

一、特点 1、侧向开启&#xff1a;与传统的顶开型窗户相比&#xff0c;侧向开敞式通风天窗采用侧向开启的方式&#xff0c;这种设计不仅为室内提供了更大的通风面积&#xff0c;还使得空气流动更加顺畅。 2、防雨功能&#xff1a;设计时考虑防雨需求&#xff0c;能够在下雨时保…

如何在C++ QT 程序中集成cef3浏览器组件去显示网页?

目录 1、问题描述 2、为什么选择cef3浏览器组件 3、cef3组件的介绍与下载 4、将cef3组件封装成sdk 5、如何使用cef3组件加载web页面 5.1、了解CefApp与CefClient 5.2、初始化与消息循环 5.3、如何创建浏览器 5.4、重载CefClient类 6、在qt客户端集成cef组件 7、最后…

VS2022上面运行QT程序

需求&#xff1a;之前是在QT6.6上面运行&#xff0c;现在想试一下VS2022&#xff1a; 操作步骤&#xff1a; 第一步&#xff1a; 在QT的配置软件中安装MSVC 第二步&#xff1a;配置VS 第三步&#xff1a;在VS上面安装QT插件&#xff0c;但是在QT上面安装速度很慢&#xff0c;…

Leetcode面试经典150题-15.三数之和

解法都在代码里&#xff0c;不懂就留言或者私信 class Solution {/**每次做这个题都想着这事最后一次了&#xff0c;但是确实很高频&#xff0c;还是多练练吧基本思路&#xff1a;先把原来的数组按照从小到大的顺序排列&#xff0c;然后我们从头开始确定第一个数&#xff0c;然…

STM32CubeMX stm32不限长度使用DMA收发串口数据

STM32CubeMX 配置 代码 stm32h7xx_it.c /*** brief This function handles UART7 global interrupt.*/ void UART7_IRQHandler(void) {/* USER CODE BEGIN UART7_IRQn 0 */if (UART7 huart7.Instance) // 判断是否是空闲中断{if (__HAL_UART_GET_FLAG(&huart7, UART_FLA…

数据导入导出(EasyExcel)框架入门指南

写在前面 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站 文章目录 EasyExcel 框架概述依赖APIExcel 实体类注解写 Excel概念介绍写 Excel 通用参数WriteWorkbookWriteSheetWriteTable 代码…

【Qt】常用控件QRadioButton

常用控件QRadioButton QRadioButton是单选按钮&#xff0c;可以在多个选项中选择一个。 作为QAbstractButton和QWidget的子类&#xff0c;其属性和用法&#xff0c;对于QRadioButton同样适用。 属性说明 checkable 是否能选中 checked 是否已经被选中. checkable 是 checked…

平安养老险宿州中支开展消防培训及逃生演练活动

近日&#xff0c;平安养老保险股份有限公司&#xff08;以下简称“平安养老险”&#xff09;宿州中心支公司邀请助安消防公司袁教官为公司员工开展消防安全知识培训。 培训教官结合近年来火灾典型案例&#xff0c;对火灾的危害、火灾的预防措施、灭火器材的使用进行深入浅出的…