Dijkstra实现单源最短路
Dijkstra算法求单源最短路
Dijkstra算法应用于求一个给定图的单个源点到其他各顶点的最短路。其中应用Dijkstra算法的图应满足如下条件
- 图中没有负权边
- 有向或者无向图都可以
- 图中若有自环或者重边也可以(需要自己先筛选一下)
Dijkstra算法的核心就是从源点开始对各个顶点进行松弛操作,且每一次松弛选择出当前最优也就是离源点最小的路径(贪心),直到求出总体最小的路径。其贪心的正确性证明可以看这个AcWing 849. Dijkstra算法(含正确性证明) - AcWing
朴素的Dijkstra算法
所谓朴素的Dijkstra就是在寻找当前未收入最短路的最小顶点时采用最朴素的遍历操作来寻找,与后面采用堆来比较朴素。
实现Dijkstra的步骤如下
- 初始化dist数组为正无穷,且令dist[s] = 0;s代表源点,dist[k]表示k顶点到源点的距离。源点本身到自身距离为0,其他顶点尚未更新默认为正无穷。
- 遍历所有顶点,从未收入最短路(st[k] == false)且更新过(dist[k] != 0x3f3f3f3f)的顶点中找到到源点距离最小的点,即为v。
- 将v收入到最短路中(st[v] = true),使用v更新v的邻接点到源点的距离,当v的邻接点到源点的距离大于v到源点再到该点的距离时,更新。
实现代码如下
849. Dijkstra求最短路 I - AcWing题库
#include <iostream>
#include <cstring>
using namespace std;
const int N = 600;
int g[N][N],dist[N]; //g[N][N],图的存储,dist[N],各顶点到源点的距离
bool st[N]; //顶点是否已经收入最短路
int n; //顶点个数
void Dijkstra(int v)// v - > 源点
{
memset(dist, 0x3f, sizeof(dist));
dist[v] = 0;
for (int i = 0; i < n; i++) //一共n个顶点,最多做n次操作即可更新所有顶点
{
int tmp = -1;
for (int j = 1; j <= n; j++)
{
if (!st[j] && (tmp == -1 || dist[tmp] > dist[j]))
tmp = j;
} //从未收入且更新过的顶点中选取最小值。由于未更新的节点为正无穷,不用特别判断也会自动被覆盖
st[tmp] = true; //将上述顶点收入
for (int j = 1; j <= n; j++)
{
if (g[tmp][j] != -1 && !st[j])//若为tmp的邻接点且未加入最短路中
{
dist[j] = min(dist[j], dist[tmp] + g[tmp][j]);
}
}
}
}
int main()
{
memset(g, -1, sizeof(g));
int m;
cin >> n >> m;
for (int i = 0; i < m; i++)
{
int x, y, z;
cin >> x >> y >> z;
g[x][y] = g[x][y] == -1 ? z : min(g[x][y], z);//若有重边,仅保留重边中较小的那条边
}
Dijkstra(1);
cout << (dist[n] == 0x3f3f3f3f ? -1 : dist[n]);
return 0;
}
几点细节
- 存储图的数组一般初始化为-1。
- 存储路径的数组初始化为无穷大,dist[源点] = 0;
- 若题目中说有重边,可以在建图时保留最小的一条边
堆优化的Dijkstra
可以看出朴素Dijkstra算法中寻找未收入的最小顶点这一步,每一次循环都要遍历一遍顶点,最坏要循环n次,也就是说这一步的时间复杂度为\(O(n^2)\)。
不妨重新审视这个操作。我们要求的只是寻找某个最小值的操作,因此可以使用小根堆这一数据结构来优化这个操作。对于n个顶点,求其最小值的时间复杂度为\(O(1)\),更新堆中的顶点的复杂度为\(O(logn)\),这样优化后的总时间复杂度为$$O(nlogn)$$
直接上代码
注意这里使用邻接表建图且STL实现的数据结构居多
850. Dijkstra求最短路 II - AcWing题库
#include <iostream>
#include <queue>
#include <vector>
#include <cstring>
using namespace std;
const int N = 1e5 + 20;
typedef pair<int, int> PII; //使用pair来存储顶点,first是该顶点的dist,second是该顶点的编号
vector<PII> g[N];
int dist[N];
bool st[N];
int n, m;
void Dijkstra(int v)
{
memset(dist, -1, sizeof(dist));
dist[v] = 0;
priority_queue<PII, vector<PII>, greater<PII>>h;//建立小根堆的方法,优先队列默认大根堆
h.push({ 0,v }); //将源点加入堆中。first为dist的目的是让其作为第一关键字进行排序
while (!h.empty()) //结束条件为队列空,也就是所有顶点都出队了
{
auto tmp = h.top();//取出最小未收录的最小顶点
h.pop();
int seq = tmp.second, distance = tmp.first;
if (st[seq]) continue;//若该顶点已经加入最短路,说明上述tmp是一个冗余元素,直接丢掉进入下一轮操作
st[seq] = true; //标记为已经加入最短路
for (int j = 0; j < g[seq].size(); j++)
{
int q = g[seq][j].first, p = g[seq][j].second;
if (dist[q] > dist[seq] + p && !st[q]) // 若可以更新同时未加入最短路中
{
dist[q] = dist[seq] + p; //更新
h.push({ dist[q],q }); //加入更新队列中
}
}
}
}
int main()
{
cin >> n >> m;
for (int i = 0; i < m; i++)
{
int x, y, z;
cin >> x >> y >> z;
g[x].push_back({y,z}); //编号,边权
}
Dijkstra(1);
cout << (dist[n] == 0x3f3f3f3f ? -1 : dist[n]);
return 0;
}
Dijkstra实现单源最短路的更多相关文章
- Dijkstra算法——单源最短路算法
一.介绍 迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他各个节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止. 适用于有 ...
- 最短路模板(Dijkstra & Dijkstra算法+堆优化 & bellman_ford & 单源最短路SPFA)
关于几个的区别和联系:http://www.cnblogs.com/zswbky/p/5432353.html d.每组的第一行是三个整数T,S和D,表示有T条路,和草儿家相邻的城市的有S个(草儿家到 ...
- [ACM_图论] Domino Effect (POJ1135 Dijkstra算法 SSSP 单源最短路算法 中等 模板)
Description Did you know that you can use domino bones for other things besides playing Dominoes? Ta ...
- 【算法系列学习】Dijkstra单源最短路 [kuangbin带你飞]专题四 最短路练习 A - Til the Cows Come Home
https://vjudge.net/contest/66569#problem/A http://blog.csdn.net/wangjian8006/article/details/7871889 ...
- 利用分支限界法求解单源最短路(Dijkstra)问题
分支限界法定义:采用Best fist search算法,并使用剪枝函数的算法称为分支界限法. 分支限界法解释:按Best first的原则,有选择的在其child中进行扩展,从而舍弃不含有最优解的分 ...
- 【算法】单源最短路——Dijkstra
对于固定起点的最短路算法,我们称之为单源最短路算法.单源最短路算法很多,最常见的就是dijkstra算法. dijkstra主要用的是一种贪心的思想,就是说如果i...s...t...j是最短路,那么 ...
- 单源最短路模板(dijkstra)
单源最短路(dijkstra算法及堆优化) 弱化版题目链接 n^2 dijkstra模板 #include<iostream> #include<cstdio> #includ ...
- 牛客编程巅峰赛S1第6场 - 黄金&钻石&王者 C.星球游戏 (单源最短路,Dijkstra)
题意:有\(n\)个点,\(m\)条双向边,两个方向的权值都是相等的,可以从\(A\)中的某个点出发走到\(B\)中的某个点,求所有路径中的最短距离,如果A和B中没有点联通,则输出\(-1\). 题解 ...
- 洛谷 P5837 [USACO19DEC]Milk Pumping G (单源最短路,dijkstra)
题意:有一\(n\)个点,\(m\)条边的双向图,每条边都有花费和流量,求从\(1\)~\(n\)的路径中,求\(max\frac{min(f)}{\sum c}\). 题解:对于c,一定是单源最短路 ...
- 2018/1/28 每日一学 单源最短路的SPFA算法以及其他三大最短路算法比较总结
刚刚AC的pj普及组第四题就是一种单源最短路. 我们知道当一个图存在负权边时像Dijkstra等算法便无法实现: 而Bellman-Ford算法的复杂度又过高O(V*E),SPFA算法便派上用场了. ...
随机推荐
- v-cloak指令用法
插值表达式存在的问题:'闪动' 如何解决该问题:使用v-cloak指令 解决该问题的原理:先隐藏,替换好值之后再显示最终的值 背后的原理:先通过样式隐藏内容,然后在内存中进行值得替换,替换好之后再显示 ...
- hello world 的并发实现
本篇文章将介绍 hello world 的并发实现,其中涉及到的知识有: 并发与并行 GPM 调度系统 并发与并行 并发不是并行.并发是同时管理很多事情,这些事情可能只做了一半就被暂停做别的事情了.而 ...
- idea 解决git更新冲突
转载请注明出处: 对使用idea工具解决git冲突,最近有发现不同的解决冲突的方法,都很快捷方便,记录一下. 1.先commit 再pull,然后手动进行merge 左边部分是本地仓库的代码,右边部分 ...
- SV 自定义数据类型
概述 自定义类型 枚举类型 定义枚举值 自定义枚举类型 枚举类型之间进行赋值是可以的 枚举类型可以赋值给整型,整型不能直接赋值给枚举类型 枚举类型 + 1 ==> 会进行隐式的转换,枚举类型转换 ...
- JS - 兼容到 IE 8
使用 jQuery可以有效的兼容IE 浏览器 , 但jQuery从2.0开始不兼容IE8,最低支持IE9,所以需要引入更低的jQuery版本来兼容 <script type="text ...
- kind-微k8s-测试与开发
0. kind 简介 开发与测试场景: 通过docker容器来模拟k8s节点 Github:https://github.com/kubernetes-sigs/kind 1. Kind 安装 os: ...
- [转帖]TiFlash DeltaTree 存储引擎设计及实现分析 - Part 1
https://tidb.net/book/book-rush/features/tiflash-code/tiflash-deltatree TiFlash 是 TiDB 的分析引擎,是 TiDB ...
- [转帖]KingbaseES 事务总结
目录 1. 什么是事务? 2. 事务的属性-ACID 3. 数据库事务的操作方式 3.1. SET TRANSACTION 3.2. BEGIN 3.3. COMMIT 3.4. ROLLBACK 3 ...
- ESXi虚拟化的坑-细微区别下虚拟机性能差异巨大
ESXi虚拟化的坑-细微区别下虚拟机性能差异巨大 背景 周末在公司无偿加班. 同组的小伙伴周一有一个需求, 我想着周六乘着机器压力不大进行一下虚拟机的clone 但是截止到晚上快十点都没有完全Clon ...
- [转帖]重置 VCSA 6.7 root密码和SSO密码
问题描述 1.用root用户登录 VMware vCenter Server Appliance虚拟机失败,无法登录 2.vCenter Server Appliance 6.7 U1的root帐户错 ...