迪杰斯特拉算法(Dijkstra)是由荷兰计算机科学家狄克斯特拉于1959年提出的,因此又 叫狄克斯特拉算法。是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最 短路径问题。迪杰斯特拉算法主要特点是从起始点开始,采用贪心算法的策略,每次遍 历到始点距离最近且未访问过的顶点的邻接节点,直到扩展到终点为止。
Dijkstra是求单源最短路问题的经典算法,单源最短路一般来说是求一个点到其他点的 最短距离,最常见的一种题型是求1号点到n号点的最短距离。
而单源最短路又分为两种,一种是边权全为正(正权值),另一种是存在负权边。Dijkstra 用来解决边权全为正的单源最短路问题,Dijkstra算法又分为朴素Dijkstra算法和堆优化 的Dijkstra算法。朴素版的Dijkstra算法的时间复杂度是O(n²),适合于稠密图,堆优化版 的Dijkstra算 法的时间复杂度是O(mlogn),适合于稀疏图。
解决存在负权边的单源最短路的算法又分为两种,一个是Bellman-Ford,一个是SPFA, SPFA是Bellman-Ford算法的优化。

以这个为例,一共三个点,绿色的数字表示点与点之间的距离,1号点到2号点的 距离是2,2号点到3号点的距离是1,1号点到3号点的距离是4,红色数字 表 示每个点到起点的距离。
按照朴素版Dijkstra算法的步骤,首先要初始化距离,1号点到起点的距离是0, 其他点到起点的距离是正无穷
然后我们就要循环3次,确定每个点到起点的距离

第一次循环明显是1号点距离起点最近,所以我们用这个点更新一下和它相连的点 距离起点的距离,也就是2,3号点,更新之后2号点距离起点的距离是2,3号点距 离起点的距离是4

第二次循环发现是2号点距离起点最近,用2号点更新一下和它相连的点距离起点的距离,也就是3号点。3号点距离起点的距离在第一次循环时更新为4,这次我们用2号点更新时可以发现,3号点距离起点的距离可以更新为3,也就1->2->3 的路线的距离小于1->4的路线,所以把3号点距离起点的距离改为3
第三次循环只剩一个点3了,这个点可以确定最短距离是3,至此循环结束,所有的点距离起点的最短距离也就确定了
上面说了朴素版Dijkstra算法适用于稠密图,稠密图用邻接矩阵来存
给定一个 n 个点 m 条边的有向图,图中可能存在重边和自环,所有边权均为正值。
请你求出 1 号点到 n 号点的最短距离,如果无法从 1 号点走到 nn 号点,则输出 −1。
输入格式
第一行包含整数 n 和 m。
接下来 m 行每行包含三个整数 x,y,z,表示存在一条从点 x 到点 y 的有向边,边长为 z。
输出格式
输出一个整数,表示 1 号点到 n 号点的最短距离。
如果路径不存在,则输出 −1。
数据范围
1≤n≤500,
1≤m≤1e5,
图中涉及边长均不超过10000。输入样例:
3 3 1 2 2 2 3 1 1 3 4输出样例:
3
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=515;
int dist[N];//每个点距离起点的距离
int g[N][N];//邻接矩阵
int n,m;
bool st[N];//存储已经确定最短路径的点
int dijkstra()
{
//初始化每个点到起点的距离
memset(dist,0x3f,sizeof dist);
//1号点到起点的距离为0
dist[1]=0;
//循环n次确定n个点到起点的最短距离
for(int i=0;i<n;i++)
{
//每次循环用t来存没有确定最短距离且距离起点最近的点
int t=-1;
for(int j=1;j<=n;j++)
{
if(!st[j]&&(t==-1||dist[j]<dist[t]))
t=j;
}
//确定了距离起点最近的点,将它标记
st[t]=true;
//用这个点更新和它相连的点距离起点的距离
for(int j=1;j<=n;j++)
dist[j]=min(dist[j],dist[t]+g[t][j]);
}
if(dist[n]==0x3f3f3f3f) return -1;
return dist[n];
}
int main()
{
cin>>n>>m;
//初始化邻接矩阵
memset(g,0x3f,sizeof g);
while(m--)
{
int a,b,c;
cin>>a>>b>>c;
//如果有重边的话,取最小的那条边,自环遍历不到不再考虑
g[a][b]=min(g[a][b],c);
}
int t=dijkstra();
cout<<t;
return 0;
}
注意:对于自环是遍历不到的,而重边只取其中最短的一条
当图为稀疏图时,也就是点数和边数在一个数量级上时我们就要用上堆优化版的Dijkstra 算法了,什么是堆优化Dijkstra算法呢?朴素版的Dijkstra算法慢就慢在寻找没有确定 最短距离且距离起点最近的点这里,这里我们用堆来找可以提高速度,这个也就是堆优化Dijkstra算法了,堆优化Dijkstra也就是对朴素版的查找部分用堆来优化了一下。
堆有两种实现方法,一个是手写堆,一个是优先队列,这里我们用优先队列来做。
步骤和朴素版类似,这里就不赘述了。
堆优化Dijkstra算法适用于稀疏图,稀疏图用邻接表来存。
给定一个 n 个点 m 条边的有向图,图中可能存在重边和自环,所有边权均为非负值。
请你求出 1 号点到 n 号点的最短距离,如果无法从 1 号点走到 n 号点,则输出 −1。
输入格式
第一行包含整数 n 和 m。
接下来 m 行每行包含三个整数 x,y,z,表示存在一条从点 x 到点 y 的有向边,边长为 z。
输出格式
输出一个整数,表示 1 号点到 n 号点的最短距离。
如果路径不存在,则输出 −1。
数据范围
1≤n,m≤1.5*1e5,
图中涉及边长均不小于 0,且不超过 10000。
数据保证:如果最短路存在,则最短路的长度不超过 1e9。输入样例:
3 3 1 2 2 2 3 1 1 3 4输出样例:
3
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N=1e6+10;
typedef pair<int,int>pll;//存储距离和编号,用于小根堆
int h[N],e[N],ne[N],idx,w[N];//邻接表,w数组表示权重,idx是两个点之间的桥梁
int n,m;
int dist[N];//每个点距离起点的距离
bool st[N];
//邻接表模板
void add(int a,int b,int c)
{
e[idx]=b;
w[idx]=c;
ne[idx]=h[a];
h[a]=idx++;
}
int dijkstra()
{
//初始化距离,1号点距离为0
memset(dist,0x3f,sizeof dist);
dist[1]=0;
//小根堆,自动升序排列
priority_queue<pll,vector<pll>,greater<pll>> heap;
heap.push({0,1});
while(heap.size())
{
//取出堆顶元素
auto t=heap.top();
//弹出堆顶元素
heap.pop();
//获得堆顶元素的距离和编号
int ver=t.second,distance=t.first;
if(st[ver]) continue;
st[ver]=true;
//通过这个点更新和它相连的点距离起点的距离
for(int i=h[ver];i!=-1;i=ne[i])
{
int j=e[i];//获得编号
//如果这个点距离起点的距离可以更新的话
if(dist[j]>distance+w[i])//遍历所有重边,使用距离最小的重边来更新
{
dist[j]=distance+w[i];
heap.push({dist[j],j});
}
}
}
if(dist[n]==0x3f3f3f3f) return -1;
return dist[n];
}
int main()
{
cin>>n>>m;
//初始化h数组
memset(h,-1,sizeof h);
while(m--)
{
int a,b,c;
cin>>a>>b>>c;
//这里不考虑重边
add(a,b,c);
}
int t=dijkstra();
cout<<t;
return 0;
}
注意:初始化点与点之间的距离时不用考虑重边的问题,我们这里用邻接表存储,会遍历所有的重边,会选择距离最小的重边更新到起点的距离
这类题不用考虑是无向图还是有向图,因为无向图是特殊的有向图,无向图可以看成有一个去的路也有一个回来的路
如有错漏之处,敬请指正!
目录一.加解密算法数字签名对称加密DES(DataEncryptionStandard)3DES(TripleDES)AES(AdvancedEncryptionStandard)RSA加密法DSA(DigitalSignatureAlgorithm)ECC(EllipticCurvesCryptography)非对称加密签名与加密过程非对称加密的应用对称加密与非对称加密的结合二.数字证书图解一.加解密算法加密简单而言就是通过一种算法将明文信息转换成密文信息,信息的的接收方能够通过密钥对密文信息进行解密获得明文信息的过程。根据加解密的密钥是否相同,算法可以分为对称加密、非对称加密、对称加密和非
1.问题描述使用Python的turtle(海龟绘图)模块提供的函数绘制直线。2.问题分析一幅复杂的图形通常都可以由点、直线、三角形、矩形、平行四边形、圆、椭圆和圆弧等基本图形组成。其中的三角形、矩形、平行四边形又可以由直线组成,而直线又是由两个点确定的。我们使用Python的turtle模块所提供的函数来绘制直线。在使用之前我们先介绍一下turtle模块的相关知识点。turtle模块提供面向对象和面向过程两种形式的海龟绘图基本组件。面向对象的接口类如下:1)TurtleScreen类:定义图形窗口作为绘图海龟的运动场。它的构造器需要一个tkinter.Canvas或ScrolledCanva
一、什么是MQTT协议MessageQueuingTelemetryTransport:消息队列遥测传输协议。是一种基于客户端-服务端的发布/订阅模式。与HTTP一样,基于TCP/IP协议之上的通讯协议,提供有序、无损、双向连接,由IBM(蓝色巨人)发布。原理:(1)MQTT协议身份和消息格式有三种身份:发布者(Publish)、代理(Broker)(服务器)、订阅者(Subscribe)。其中,消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者。MQTT传输的消息分为:主题(Topic)和负载(payload)两部分Topic,可以理解为消息的类型,订阅者订阅(Su
TCL脚本语言简介•TCL(ToolCommandLanguage)是一种解释执行的脚本语言(ScriptingLanguage),它提供了通用的编程能力:支持变量、过程和控制结构;同时TCL还拥有一个功能强大的固有的核心命令集。TCL经常被用于快速原型开发,脚本编程,GUI和测试等方面。•实际上包含了两个部分:一个语言和一个库。首先,Tcl是一种简单的脚本语言,主要使用于发布命令给一些互交程序如文本编辑器、调试器和shell。由于TCL的解释器是用C\C++语言的过程库实现的,因此在某种意义上我们又可以把TCL看作C库,这个库中有丰富的用于扩展TCL命令的C\C++过程和函数,所以,Tcl是
我一直在尝试用Ruby实现Luhn算法。我一直在执行以下步骤:该公式根据其包含的校验位验证数字,该校验位通常附加到部分帐号以生成完整帐号。此帐号必须通过以下测试:从最右边的校验位开始向左移动,每第二个数字的值加倍。将乘积的数字(例如,10=1+0=1、14=1+4=5)与原始数字的未加倍数字相加。如果总模10等于0(如果总和以零结尾),则根据Luhn公式该数字有效;否则无效。http://en.wikipedia.org/wiki/Luhn_algorithm这是我想出的:defvalidCreditCard(cardNumber)sum=0nums=cardNumber.to_s.s
下面是我写的一个计算斐波那契数列中的值的方法:deffib(n)ifn==0return0endifn==1return1endifn>=2returnfib(n-1)+(fib(n-2))endend它工作到n=14,但在那之后我收到一条消息说程序响应时间太长(我正在使用repl.it)。有人知道为什么会这样吗? 最佳答案 Naivefibonacci进行了大量的重复计算-在fib(14)fib(4)中计算了很多次。您可以将内存添加到您的算法中以使其更快:deffib(n,memo={})ifn==0||n==1returnnen
为了防止在迁移到生产站点期间出现数据库事务错误,我们遵循了https://github.com/LendingHome/zero_downtime_migrations中列出的建议。(具体由https://robots.thoughtbot.com/how-to-create-postgres-indexes-concurrently-in概述),但在特别大的表上创建索引期间,即使是索引创建的“并发”方法也会锁定表并导致该表上的任何ActiveRecord创建或更新导致各自的事务失败有PG::InFailedSqlTransaction异常。下面是我们运行Rails4.2(使用Acti
我正在开发一个类似微论坛的项目,其中一个特殊用户发布一条快速(接近推文大小)的主题消息,订阅者可以用他们自己的类似大小的消息来响应。直截了当,没有任何形式的“挖掘”或投票,只是每个主题消息的响应按时间顺序排列。但预计会有很高的流量。我们想根据它们引起的响应嗡嗡声来标记主题消息,使用0到10的等级。在谷歌上搜索了一段时间的趋势算法和开源社区应用示例,到目前为止已经收集到两个有趣的引用资料,但我还没有完全理解它们:Understandingalgorithmsformeasuringtrends,关于使用基线趋势算法比较维基百科页面浏览量的讨论,在SO上。TheBritneySpearsP
我收到错误:unsupportedcipheralgorithm(AES-256-GCM)(RuntimeError)但我似乎具备所有要求:ruby版本:$ruby--versionruby2.1.2p95OpenSSL会列出gcm:$opensslenc-help2>&1|grepgcm-aes-128-ecb-aes-128-gcm-aes-128-ofb-aes-192-ecb-aes-192-gcm-aes-192-ofb-aes-256-ecb-aes-256-gcm-aes-256-ofbRuby解释器:$irb2.1.2:001>require'openssl';puts
文章目录一.Dijkstra算法想解决的问题二.Dijkstra算法理论三.java代码实现一.Dijkstra算法想解决的问题解决的问题:求解单源最短路径,即各个节点到达源点的最短路径或权值考察其他所有节点到源点的最短路径和长度局限性:无法解决权值为负数的情况二.Dijkstra算法理论参数:S记录当前已经处理过的源点到最短节点U记录还未处理的节点dist[]记录各个节点到起始节点的最短权值path[]记录各个节点的上一级节点(用来联系该节点到起始节点的路径)Dijkstra算法步骤:(1)初始化:顶点集S:节点A到自已的最短路径长度为0。只包含源点,即S={A}顶点集U:包含除A外的其他顶