再述 Dijkstra

news/2025/1/29 6:24:55/文章来源:https://www.cnblogs.com/Atserckcn/p/18691127

再述 Dijkstra

学 Dijkstra 好久了,今天再学了一遍,感觉推翻了好多自己的知识……

定义

一种用于求非负权值的图的单源最短路径的算法。

方法

已知:如果要求从起始点 s 到某一个点 x 的最短路径,显然只能从某一个已确认为最短路径的点转移。

给个图:

假设我们的起始点是点 1,现在我们用数组记录从原点到所有点的最短路径:

1 2 3 4 5
0 \(\infty\) \(\infty\) \(\infty\) \(\infty\)

由于其他点的最短路未知,故先用 \(\infty\) 代替,代码中用很大的一个数字代替即可。

注意到,我们由于要求出某个点出发,所有点的最短路,显然需要更新 \(n\) 次,其中 \(n\) 为顶点数量。

在这 \(n\) 次循环中,我们可以处理出由若干顶点组成的已知最短路集合,称之为 \(K\)

在每次循环中,用 \(O(n)\) 可以找到距离 \(u(u\in K)\) 最近的那个点,更新其最短路表格,并将其加入 \(K\)​ 中。

最后得到的结果:

1 2 3 4 5
0 5 6 7 6

证明

如何证明这种算法是对的?

假设我们有一张图:

\(a\) 出发,求到 \(e\) 的最短路径。其中 \(a\rightarrow b\rightarrow e\) 这条路径已确认最短。

显然 \(a\rightarrow c \rightarrow d\) 这条路径并不会比 \(a\rightarrow b\rightarrow e\) 更优,且 \(d\rightarrow e\) 这条边的权值一定非负(前提),所以 \(a\rightarrow b \rightarrow e\) 这条路径一定是最优的。

算算时间复杂度,两层 \(O(n)\) 的循环,就 \(O(n^2)\),对于小数据可过。可允许大小约在 \(n\le 10^4\)

优先队列优化

想想能否优化时间复杂度?

注意到,由于是要求 \(n\) 个点的最短路,那么第一层的循环显然不能舍弃。

考虑优化时找到最近点的枚举步骤。

可以用一个优先队列存起来。存的东西:pair 类型,第一个元素是目前的最短路距离,第二个是点的编号。

那么众所周知,优先队列查找一个元素的时间复杂度是 \(O(\log n)\) 的,其中 \(n\) 为元素个数。

每次查找都是一个 \(O(\log n)\)\(n\) 次外循环,每次还要通过 \(O(m)\) 的时间复杂度更新最短距离。

所以时间复杂度即为 \(O((n+m)\log n)\)

一般来说,只要图是联通的,\(m\) 基本都会比 \(n\) 大,可近似为 \(O (m\log n)\)​。

局限性

但是,考虑到一种特殊的情况:完全图。

众所周知,完全图是一种 \(m=n(n-1)\) 的特殊图,那么优先队列优化的时间复杂度就反而退化成了 \(O(n^2 \log n)\),反而不如朴素版。

代码

放下优先队列优化后的代码:

#include<bits/stdc++.h>
using namespace std;
const int MAXM=5e5+5;
const int MAXN=1e4+5;
int n,m,s;
bool book[MAXN];
int dis[MAXN];
struct EDGE{int to,w,pre;
}edge[MAXM];
int head[MAXN];
priority_queue<pair<int,int>,vector<pair<int,int> > ,greater<pair<int,int> > > heap;
void init()
{for(int i=1;i<=n;i++){dis[i]=INT_MAX;}return;
}
void add(int from,int to,int w,int num)
{edge[num].to=to;edge[num].w=w;edge[num].pre=head[from];head[from]=num;return;
}
int u,v,w;
int main(){scanf("%d%d%d",&n,&m,&s);init();dis[s]=0;for(int i=1;i<=m;i++){scanf("%d%d%d",&u,&v,&w);add(u,v,w,i);}heap.push(make_pair(0,s));while(!heap.empty()){int t=heap.top().second;heap.pop();if(book[t]==true){continue;}book[t]=true;for(int i=head[t];i!=0;i=edge[i].pre){dis[edge[i].to]=min(dis[edge[i].to],dis[t]+edge[i].w);heap.push(make_pair(dis[edge[i].to],edge[i].to));}}for(int i=1;i<=n;i++){printf("%d ",dis[i]);}puts("");return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Docker 常见问题处理技巧

Docker 迁移存储目录默认情况系统会将 Docker 容器存放在 /var/lib/docker 目录下问题起因今天通过监控系统,发现公司其中一台服务器的磁盘块慢,随即上去看了下,发现 /var/lib/docker 这个目录特别大。由上述原因,我们都知道,在 /var/lib/docker 中存储的都是相关于容器的…

drools 规则引擎和 solon-flow 哪个好?solon-flow 简明教程

做电子政务的项目时,经常会有大量的业务逻辑变更,但其实里面的业务改动,其实就是一些业务逻辑变动。而程序员编写的代码也没有任何技术含量,跟着式样书逐字逐句的翻译就行。大量的 `if/else` 判断遍布整个项目,维护难度极大。而这个 solon-flow 流引擎,可以方便的将业务的…

drools 规则引擎和 solon-flow 哪个好? 规则引擎 solon-flow 简明教程

做电子政务的项目时,经常会有大量的业务逻辑变更,但其实里面的业务改动,其实就是一些业务逻辑变动。而程序员编写的代码也没有任何技术含量,跟着式样书逐字逐句的翻译就行。大量的 `if/else` 判断遍布整个项目,维护难度极大。而这个 solon-flow 流引擎,可以方便的将业务的…

D28 Service 代理模式

当访问Service的IP地址时,流量会转发到后端Pod,那这个转发是怎么实现的呢?Service是一个抽象的资源对象,主要用于定义端口映射规则。具体的流量转发工作由kube-proxy组件负责,它利用主机上的iptables和IPVS技术来实现具体的网络转发,如下图所示:kube-proxy组件默认使用i…

05_LaTeX之排版样式设定

本章内容将一览如何修改 $\LaTeX{}$ 的排版样式。05_\(\LaTeX{}\) 之排版样式设定 目录05_\(\LaTeX{}\) 之排版样式设定字体和字号字体样式字号选用字体宏包字体编码使用 fontspec 宏包更改字体在 ctex 宏包或文档类中更改中文字体使用 unicode-math 宏包配置 Unicode 数学字体…

第十章 输入输出系统

第十章 输入输出系统 本文是对《操作系统真象还原》第十章学习的笔记,欢迎大家一起交流,目前所有代码已托管至 fdx-xdf/MyTinyOS 。 上一章遗留的问题 在上一节中,我们实现了多线程轮转调度,但是当我们运行一段时间后,就会发生GP异常 ​​ 待解决的几个问题:输出中,有些…

【每日一题】20250125

不等和等下去,同样苦涩。【每日一题】已知变量 \(x\) 和变量 \(y\) 的一组成对样本数据为 \((x_i,y_i)(i=1,2,3,\cdotp\cdotp\cdotp,8)\),其中 \(\overline{x}=\frac98\),其回归直线方程为 \(\hat{y}=2x-\frac14\),当增加两个样本数据 \((-1,5)\) 和 \((2,9)\) 后,重新得到…

云手机还是会被检测!还能用来多开吗?

云手机还是会被检测!还能用来多开吗? 云手机确实可以用于多开,但是否会被检测到以及是否安全,取决于多种因素,包括云手机服务提供商的技术、用户的操作方式以及目标应用(如微信、游戏等)的检测机制。以下是关于云手机多开的安全性和可行性的详细分析:云手机多开的原理 …

P1038神经网络

神经网络 题目背景 人工神经网络(Artificial Neural Network)是一种新兴的具有自我学习能力的计算系统,在模式识别、函数逼近及贷款风险评估等诸多领域有广泛的应用。对神经网络的研究一直是当今的热门方向,兰兰同学在自学了一本神经网络的入门书籍后,提出了一个简化模型,…

Phi小模型开发教程:C#使用本地模型Phi视觉模型分析图像,实现图片分类、搜索等功能

大家好,我是编程乐趣。 我们都知道,要实现对结构化的数据(文本)搜索是比较容易的,但是对于非结构化的数据,比如图片,视频就没那么简单了。 但是现在有了AI模型,实现图片分类、搜索等功能,就变得容易很多。 在前面的文章里,我们有提到:Phi-vision 是一个拥有 42 亿参…

E95 01分数规划+树上背包 P1642 规划

视频链接: P1642 规划 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)// 01分数规划+树上背包 复杂度:n*m*log(1e9) #include <bits/stdc++.h> using namespace std;int read(){int x=0,f=1;char c=getchar();while(!isdigit(c)){if(c==-)f=-1;c=getchar();}while(is…