ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

dijkstra 学习笔记(未更完)

2022-08-01 20:35:50  阅读:188  来源: 互联网

标签:node int 路径 算法 笔记 学习 dijkstra vec INF


0 题外话

没想到23个月没碰过最短路的我提交了4次就~直接过了!

顺便整理一下dijkstra的知识

本篇题解可能对题目阐述较少(?)

有错漏之处请及时通知,望海涵


1 引入

迪杰斯特拉算法(Dijkstra)是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法。这是从一个顶点到其余各顶点的最短路径算法,解决的是正权图中最短路径问题。迪杰斯特拉算法主要特点是从起始点开始,采用贪心算法的策略,每次遍历到始点距离最近且未访问过的顶点的邻接节点,直到扩展到终点为止


2 算法介绍

dijkstra算法是一种非常巧妙的算法:

此算法可以在 $O((m+n)log n)$ 的时间复杂度内,解决正权图的单源最短路问题

2.1 基础变量介绍

$n$:节点个数 $m$:边的个数 $s$:起点编号 $e$:中点编号

$d[i]$:$distance$ 间距,表示当前从起点到点 $i$ 的最短路径的最小值

$v[i]$:$visit$ 访问,表示当前有没有访问(更新)节点 $i$

$struct$ $node$ { $int$ $to,$ $w$ }:$edge$ 边, $to$ 表示边的终点,$w$ 表示边的权值

$vector$ <$node$> $vec[i][j]$:$edge$ 存边(仅仅是作者习惯,向量命名为 $vec$ ),表示起点为 $i$ 的第 $j$ 条边 (终点为 $vec[i][j].to$,权值为 $vec[i][j].w$ )

2.2 变量初始化

首先我们观察 $d$ 数组与 $v$ 数组的定义

通过定义,明显可以得出:

//INF为极大值,n为节点个数,x为起点
void intt()
{
    for(int i = 1;i <= n;++ i) d[i] = INF;//一开始,所有边都不与起点连通,所以距离设为无穷大
    for(int i = 1;i <= n;++ i) v[i] = false;///一开始,所有边都不与起点连通
    d[x] = 0;//起点到自己的距离为0
    v[x] = true;//起点与自己连通
}

接着我们看到结构体 $node$ 和向量 $vec$

只要在输入每一条边时插入就彳亍了:

struct node
{//node存放边 
	int to, w;
	//to表示路径终点,w表示路径权值
};

......

int main()
{
    cin >> n >> m >> s >> e;//输入
    for(int i = 1, u, v, w;i <= m;++ i)
    {//u代表路径起点,v代表路径终点,w代表路径长度,m为边的个数
    	cin >> u >> v >> w;
    	vec[u].push_back((node) {v, w});//建边 
    	vec[v].push_back((node) {u, w});//建反边
		//因为是无向图,建两条边,有向图就只用建一条
	}
}

2.3 算法原理

建议联系上两个小节内容,更容易理解

我们先观察一个比较简单的图:

图一

我们观察节点1到节点3的最短路:很明显路径顺序为1 -> 4 -> 3

我们再手算求出 $d$ 数组的值:

$d[1]$ $=$ $0,$ $d[2]$ $=$ $3,$ $d[3]$ $=$ $11,$ $d[4]$ $=$ $4$(很显然,$d[3] = ans$)

那么如何编程求 $d$ 数组的值呢?

结论一:$d[i] = Min(d[u] + w[u$ -> $u])$(假设此时 $Min(d[u] + w[u$ -> $u])$ 可以被推出来)

注:$u \in$ 以 $i$ 为一端点的边的端点,$w[u$ -> $v]$ 表示以 $u, v$ 为端点的边的权值

比如,d[2] = min(d[1] + 3, d[3] + 10)

结论二:最短路径为简单路径!

注意我们讨论的是正权图

直观上理解,就是如果有环,那么把环去掉,最短路径长度更短

证明可以参考:(不是吧,我竟然没找到qwq)

3 算法详解

3.1 算法流程:

$dijkstra$ 的算法流程如下:

1.初始化:可以参考 2.3 小节,将起点插入集合 $S$

2.维护:将所有集合 $S$ 中的点集划分成两个集合,已更新的集合和未更新的集合

3.查询:在已更新的集合中,找到 $d$ 数组值最小的点,没有就退出循环

4.更新:$d[x]$ 已经是目前 $x$ 的最短路径了! 更新所有 $x$ 的出边

5.返回:将点 $x$ 推出集合,将所有刚更新的点加入集合

当然,我们可以用优先队列与 $v$ 数组来更快的执行返回操作

3.2 样例详解

图一

题目:求出 1 到所有结点最短路的值

首先,分析初始全局变量:

$vec[1][0] = $

$d[1] = 0$, $d[2] = INF$, $d[3] = INF$, $d[4] = INF$, $d[5] = INF$

$v[1] = true$, $v[2] = false, $v[3] = false$, $v[4] = false$, $v[5] = false$

标签:node,int,路径,算法,笔记,学习,dijkstra,vec,INF
来源: https://www.cnblogs.com/STL-Charlie/p/16541714.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有