Dijkstra(迪杰斯特拉)单源最短路径算法

Dijkstra思想

Dijkstra是一种求单源最短路径的算法。

Dijkstra仅仅适用于非负权图,但是时间复杂度十分优秀。

Dijkstra算法主要思想是:

主要思想是,将结点分成两个集合:已确定最短路长度的,未确定的。

一开始第一个集合里只有节点V。

然后重复这些操作:

1.对那些刚刚被加入第一个集合的结点的所有出边执行松弛操作。

2.从第二个集合中,选取一个最短路长度最小的结点,移到第一个集合中。

用暴力算法的时间复杂度是Ο(n2+m) = Ο(n2)。

用小根堆优化的时间复杂度是Ο(m log n)。

还有一些复杂的实现Dijkstra算法,比如说:priority_queue(时间复杂度:Ο(m log m))

                    ZKW线段树(时间复杂度:O(m log n + n) = Ο(m log n))

                    fibonacci堆(时间复杂度:Ο(n log n + m))

感兴趣的OIer想具体了解这几种方法,可以上网查一查,这里不多赘述。

Dijkstra暴力法例题

Dijkstra小根堆优化例题

Dijkstra暴力法代码

// by kyrence
#include <bits/stdc++.h>
using namespace std; const int S = 3e3 + , INF = 0x3f3f3f3f;
int adj[S][S], dist[S], n, m;
bool vis[S]; void dijkstra() {
memset(dist, INF, sizeof(dist));
memset(vis, , sizeof(vis));
dist[] = ;
for (int i = ; i < n; i++) {
int x = ;
for (int j = ; j <= n; j++) //找到未标记的节点中dist最小的节点对其它节点进行更新
if (!vis[j] && (!x || dist[j] < dist[x]))
x = j;
vis[x] = ;
for (int j = ; j <= n; j++) //更新其它节点的最短路
dist[j] = min(dist[j], dist[x] + adj[x][j]);
}
} int main() {
memset(adj, INF, sizeof(adj)); //构建邻接矩阵
scanf("%d%d", &n, &m);
for (int i = ; i <= n; i++) adj[i][i] = ; //节点V到节点V的距离为0
for (int i = ; i <= m; i++) {
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
adj[x][y] = z; //有向图
//adj[x][y] = adj[y][x] = z; 无向图
}
dijkstra(); //dijkstra暴力法求解单源最短路径
for (int i = ; i <= n; i++)
printf("%d\n", (dist[i] == INF ? - : dist[i])); //-1代表节点1到节点i没有路径
return ;
}

Dijkstra小根堆优化代码

// by kyrence
#include <bits/stdc++.h>
using namespace std; const int N = 1e5 + , M = 1e6 + , INF = 0x3f3f3f3f;
int head[N], ver[M], edge[M], Next[M], dist[N]; //构建邻接表
int n, m, tot;
bool vis[N];
priority_queue<pair<int, int> > q; //小根堆第一项取负,使小根堆变成大根堆
//在不使用小顶优先队列情况下取负将小根堆变成大根堆加速优先队列,常见的加速技巧 void add(int x, int y, int data) { //邻接表存储图
ver[++tot] = y;
edge[tot] = data;
Next[tot] = head[x];
head[x] = tot;
} void dijkstra() {
memset(dist, INF, sizeof(dist));
memset(vis, , sizeof(vis));
dist[] = ; q.push(make_pair(, ));
while (!q.empty()) {
int u = q.top().second; q.pop(); //找到未访问节点中dist最小的节点
if (vis[u]) continue; //如果节点u已经访问则忽略
vis[u] = ;
for (int i = head[u]; i; i = Next[i]) { //邻接表访问出边
int y = ver[i], z = edge[i];
if (dist[y] > dist[u] + z) {
dist[y] = dist[u] + z; //更新节点
q.push(make_pair(-dist[y], y)); //取负值,加速小根堆
}
}
}
} int main() {
scanf("%d%d", &n, &m);
for (int i = ; i <= m; i++) {
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
add(x, y, z); //无向图
//add(x, y, z); add(y, x, z); 有向图
}
dijkstra(); //dijkstra小根堆优化求解单源最短路径
for (int i = ; i <= n; i++)
printf("%d\n", (dist[i] == INF ? - : dist[i])); //-1代表节点1到节点i没有路径
return ;
}

力荐使用小根堆优化,代码简洁直观易懂,空间小,时间复杂度优。

Dijkstra求解单源最短路径的更多相关文章

  1. Dijkstra算法——单源最短路径问题

    学习一个点到其余各个顶点的最短路径--单源最短路径 Dijkstra算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有向 ...

  2. 单源最短路径——dijkstra算法

    dijkstra算法与prim算法的区别   1.先说说prim算法的思想: 众所周知,prim算法是一个最小生成树算法,它运用的是贪心原理(在这里不再证明),设置两个点集合,一个集合为要求的生成树的 ...

  3. [C++]单源最短路径:迪杰斯特拉(Dijkstra)算法(贪心算法)

    1 Dijkstra算法 1.1 算法基本信息 解决问题/提出背景 单源最短路径(在带权有向图中,求从某顶点到其余各顶点的最短路径) 算法思想 贪心算法 按路径长度递增的次序,依次产生最短路径的算法 ...

  4. 【转】Dijkstra算法(单源最短路径)

    原文:http://www.cnblogs.com/dolphin0520/archive/2011/08/26/2155202.html 单源最短路径问题,即在图中求出给定顶点到其它任一顶点的最短路 ...

  5. 单源最短路径Dijkstra算法,多源最短路径Floyd算法

    1.单源最短路径 (1)无权图的单源最短路径 /*无权单源最短路径*/ void UnWeighted(LGraph Graph, Vertex S) { std::queue<Vertex&g ...

  6. 单源最短路径算法:迪杰斯特拉 (Dijkstra) 算法(二)

    一.基于邻接表的Dijkstra算法 如前一篇文章所述,在 Dijkstra 的算法中,维护了两组,一组包含已经包含在最短路径树中的顶点列表,另一组包含尚未包含的顶点.使用邻接表表示,可以使用 BFS ...

  7. 单源最短路径算法:迪杰斯特拉 (Dijkstra) 算法(一)

    一.算法介绍 迪杰斯特拉算法(英语:Dijkstra's algorithm)由荷兰计算机科学家艾兹赫尔·迪杰斯特拉在1956年提出.迪杰斯特拉算法使用了广度优先搜索解决赋权有向图的单源最短路径问题. ...

  8. SPFA解决单源最短路径

    SPFA(Shortest Path Faster Algorithm): 一:基本算法 在求解单源最短路径的时候,最经典的是 Dijkstra 算法,但是这个算法对于含有负权的图就无能为力了,而 B ...

  9. JAVA之单源最短路径(Single Source Shortest Path,SSSP问题)dijkstra算法求解

    题目简介:给定一个带权有向图,再给定图中一个顶点(源点),求该点到其他所有点的最短距离,称为单源最短路径问题. 如下图,求点1到其他各点的最短距离 准备工作:以下为该题所需要用到的数据 int N; ...

随机推荐

  1. post提交方式为什么要序列化,而Get提交方式就不用?序列化做了什么?

    这是因为后台能够直接处理的数据格式,是一种经过序列化的键值对数据,比如前端要向后台提交三个参数,分别是a=1,b=2,c=3,那么后台接收到的数据就应该是a=1&b=2&c=3(可以看 ...

  2. js中的克隆

    1.如果克隆对象是基本类型,直接复制就可以 <script type="text/javascript"> var str1 = 'abc' var str2 = st ...

  3. Linux 内核 嵌入的 kobjects

    在我们进入细节前, 值得花些时间理解如何使用 kobjects. 如果你回看被 kobjects 处 理的函数列表, 你会看到它们都是代表其他对象进行的服务. 一个 kobject, 换句话说, 对其 ...

  4. supported platform

    Target name Platform Architecture Endianness Developer(s) Known Issues/Notes adm5120 Infineon/ADMtek ...

  5. Cisco DNA-C POC环境配置

    Step1:在DNA-C上创建Site,本例创建Global->China->WangJiang->20 F如下图: Step2:配置fusion区域的AAA和NTP等信息,如下图: ...

  6. jdbc链接Oracle数据库的封装

    在src下创建properties文件 driver=oracle.jdbc.driver.OracleDriverurl=jdbc:oracle:thin:@//127.0.0.1:1521/XEu ...

  7. K:缓存数据库双写数据一致性方案

    对于缓存和数据库双写,其存在着数据一致性的问题.对于数据一致性要求较高的业务场景,我们通常会选择使用分布式事务(2pc.paxos等)来保证缓存与数据库之间的数据强一致性,但分布式事务的复杂性与对资源 ...

  8. vmware安装ubuntu的简单配置

    介绍:ubuntu是一个桌面体验比较好的linux操作系统,尝试使用vmware安装一个虚拟机试用一下,做个简单记录,安装操作系统步骤省略 一.配置root用户,并使用root登录图像界面 Ubunt ...

  9. centos服务器cpu百分之百,top查询不到之“-bash”

    把这条注释掉. [root@aaaa ~]# cat /etc/ld.so.preload #/usr/local/lib/libproc.so[root@aaaa ~]# 然后在top

  10. Mybatis是如何实现SQL防注入的

    Mybatis这个框架在日常开发中用的很多,比如面试中经常有一个问题:$和#的区别,它们的区别是使用#可以防止SQL注入,今天就来看一下它是如何实现SQL注入的. 什么是SQL注入 在讨论怎么实现之前 ...