【图论】Dijkstra算法(基础版)

一.简介

Dijkstra算法(迪杰斯特拉算法) 用来计算从一个点到其他所有点的最短路径算法,是一种单源最短路径算法。


二.简要步骤

  1. 初始化距离数组和已访问数组。将起始节点的距离设为0,其他节点的距离设为无穷大。
  2. 选择距离数组中未访问节点中距离最小的节点,将其标记为已访问。
  3. 遍历该节点的所有邻居节点,更新它们的距离。如果通过当前节点到达邻居节点的路径比已知的最短路径更短,则更新距离数组中的值。
  4. 重复步骤2和步骤3,直到所有节点都被访问过或者没有可达节点。

最终,距离数组中记录的就是起始节点到其他所有节点的最短路径长度。如果需要找到具体的最短路径,可以在算法执行过程中维护一个前驱节点数组,记录每个节点的前驱节点,从而可以回溯得到最短路径。


三.时间复杂度

Dijkstra算法的时间复杂度取决于图的规模,通常为O(V^2),其中V是节点的数量。

然而,通过使用优先队列等数据结构,可以将时间复杂度优化到O((V+E)logV),其中E是边的数量。(下篇文章介绍)


四.详解Dijkstra基础版

步骤一:

初始化,所有点之间的距离都无穷大。然后根据题目条件更新数据。详细见后面的代码注释。

步骤二:

贪心策略,找出距离起点最小的点,利用它进行搭桥,然后标记,下次就不用了。

​
int pos=0,minn=0x7fffffff;
//贪心,找出距离起点最近点,搭桥 
for(int j=1;j<=n;j++){
	if(dis[j]

步骤三:

进行搭桥,如果效果好,就更新数据。

​
for(int j=1;j<=n;j++){
	if(dis[pos]+g[pos][j]

步骤四:

把步骤二和步骤三循环n-1次即可。也就是vis完所有数据,dis全为最小值。


五.题目

题目描述:

输出起点到各个点的最短路径

输入说明:

第一行输入三个数,分别表示点的个数,边的个数,起点

第二行输入m行数据,一行中有三个数字,分别表示从u点到v点的距离为w;

输出说明:

输出起点到各个点的最短路径

输入样例:

5 7 1
1 2 2
1 3 4
1 4 7
2 3 1
2 5 2
3 4 1
3 5 6

输出样例:

0 2 3 4 4


六.【AC】代码 

/*
5 7 1
1 2 2
1 3 4
1 4 7
2 3 1
2 5 2
3 4 1
3 5 6
*/

//Dijkstra
#include
#define maxn 101
using namespace std;
int n,m,s;  //n个点,m条边,s为起点。
int g[maxn][maxn]; //邻接矩阵存边
int dis[maxn]; //起点到i点的距离
bool vis[maxn]; 

void dijkstra(){
	//每个点到起点的距离初始为0x3f3f3f3f,即无限大,表示不可到达
	memset(dis,0x3f,sizeof(dis)); 
	dis[s]=0; //起点到起点距离为0
	vis[s]=1;
	for(int i=1;i<=n;i++){
		if(i!=s){
			dis[i]=g[s][i]; //同步过来 
		}
	} 
	//因为已经标记起点了,从2开始,每次遍历标记1个点,直到全部标记 
	for(int i=2;i<=n;i++){
		int pos=0,minn=0x7fffffff;
		//贪心,找出距离起点最近点,搭桥 
		for(int j=1;j<=n;j++){
			if(dis[j]>n>>m>>s;
	//初始化 
	//每条边的距离都初始为0x3f3f3f3f,即无限大,表示不可走
	memset(g,0x3f,sizeof(g));  
	for(int i=1;i<=n;i++) g[i][i]=0;  //每个点到自己的距离都为0
	for(int i=1;i<=m;i++){
		int u,v,w;
		cin>>u>>v>>w;
		g[u][v]=w;
	}
	//算法
	dijkstra();
	for(int i=1;i<=n;i++){
		cout<

你可能感兴趣的:(图论,图论,算法,c++)