单源最短路——朴素Dijkstra&堆优化版
朴素Dijkstra 是一种基于贪心的算法。
稠密图使用二维数组存储点和边,稀疏图使用邻接表存储点和边。
算法步骤:
1.将图上的初始点看作一个集合S,其它点看作另一个集合
2.根据初始点,求出其它点到初始点的距离dist[i] (若相邻,则dist[i]为边权值;若不相邻,则dist[i]为无限大)
3.选取最小的dist[i](记为dist[x]),并将此dist[i]边对应的点(记为x)加入集合S(实际上,加入集合的这个点的dist[x]值就是它到初始点的最短距离)
4.再根据x,更新跟 x 相邻点 y 的dist[y]值:dist[y] = min{ dist[y], dist[x] + 边权值g[x] [y] },因为可能会把距离调小,所以这个更新操作叫做松弛操作。
(仔细想想,为啥只更新跟x相邻点的dist[y],而不是更新所有跟集合 s 相邻点的 dist 值? 因为第三步只更新并确定了x点到初始点的最短距离,集合内其它点是之前加入的,也经历过第 4 步,所以与 x 没有相邻的点的 dist值是已经更新过的了,不会受到影响)
5.重复3,4两步,直到目标点也加入了集合,此时目标点所对应的dist[i]即为最短路径长度。
朴素版Dijkstra模板(时间复杂度为O(n²)):
int n, m; //存储点数和边数
int g[][]; //存储图
int dist[]; //每个点到1号点的距离
bool v[]; //标记是否已经访问过该点
void dijkstra()
{
memset( dist, 0x3f3f3f, sizeof dist);
dist[1] = 0;
for( int i = 1; i <= n; i++) //遍历每个点
{
int t = -1;
for( int j = 1; j <= n; j++) //找到未访问过且距离源点距离最小的点
if( !v[j] && (t == -1 || dist[t] > dist[j]))
t = j;
v[t] = true; //标记为已访问
for( int j = 1; j <= n; j++)
dist[j] = min( dist[j], dist[t]+g[t][j]);
}
}
堆优化版Dijkstra模板(时间复杂度为O(m㏒n)):
typedef pair<int, int> PII;
const int N = 1e5 + 10;
int n, m;
int h[N], w[N], e[N], ne[N], idx;//单链表模拟邻接表存储图
int dist[N]; //每个点到1号点的距离
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()
{
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
priority_queue<PII, vector<PII>, greater<PII>> 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];
}
单源最短路——朴素Dijkstra&堆优化版的更多相关文章
- 洛谷P3371单源最短路径Dijkstra堆优化版及优先队列杂谈
其实堆优化版极其的简单,只要知道之前的Dijkstra怎么做,那么堆优化版就完全没有问题了. 在做之前,我们要先学会优先队列,来完成堆的任务,下面盘点了几种堆的表示方式. priority_queue ...
- 单源最短路问题--朴素Dijkstra & 堆优化Dijkstra
许久没有写博客,更新一下~ Dijkstra两种典型写法 1. 朴素Dijkstra 时间复杂度O(N^2) 适用:稠密图(点较少,分布密集) #include <cstdi ...
- 单源最短路:Dijkstra算法 及 关于负权的讨论
描述: 对于图(有向无向都适用),求某一点到其他任一点的最短路径(不能有负权边). 操作: 1. 初始化: 一个节点大小的数组dist[n] 源点的距离初始化为0,与源点直接相连的初始化为其权重,其他 ...
- UVA 11374 Airport Express 机场快线(单源最短路,dijkstra,变形)
题意: 给一幅图,要从s点要到e点,图中有两种无向边分别在两个集合中,第一个集合是可以无限次使用的,第二个集合中的边只能挑1条.问如何使距离最短?输出路径,用了第二个集合中的哪条边,最短距离. 思路: ...
- 【一个蒟蒻的挣扎】单源最短路(Dijkstra)
赛前没啥时间好好解释了,还有三天2019CSP,大家加油啊!!! ヾ(◍°∇°◍)ノ゙ 背掉它就好啦!!! 我觉得我这一版打得还行就放上来了 #include<cstdio> #inclu ...
- 单源最短路模板(dijkstra)
单源最短路(dijkstra算法及堆优化) 弱化版题目链接 n^2 dijkstra模板 #include<iostream> #include<cstdio> #includ ...
- Dijkstra堆优化+邻接表
Dijkstra算法是个不错的算法,但是在优化前时间复杂度太高了,为O(nm). 在经过堆优化后(具体实现用的c++ STL的priority_queue),时间复杂度为O((m+n) log n), ...
- 最短路模板(Dijkstra & Dijkstra算法+堆优化 & bellman_ford & 单源最短路SPFA)
关于几个的区别和联系:http://www.cnblogs.com/zswbky/p/5432353.html d.每组的第一行是三个整数T,S和D,表示有T条路,和草儿家相邻的城市的有S个(草儿家到 ...
- 最短路-朴素版Dijkstra算法&堆优化版的Dijkstra
朴素版Dijkstra 目标 找到从一个点到其他点的最短距离 思路 ①初始化距离dist数组,将起点dist距离设为0,其他点的距离设为无穷(就是很大的值) ②for循环遍历n次,每层循环里找出不在S ...
随机推荐
- 安装 PHP 镜像
安装 PHP 镜像 方法一.通过 Dockerfile 构建 创建Dockerfile 首先,创建目录php-fpm,用于存放后面的相关东西. runoob@runoob:~$ mkdir -p ~/ ...
- leaflet地图框架
leaflet 中文API LeafLet js 官网:http://leafletjs.com/index.html LeafLet js 官网demo: http://leafletjs.com/ ...
- BurpSuite intuder里保存所有网页的特定内容:以bugku的cookies欺骗为例题
这题里想读取index.php只能一行一行的读,通过控制line参数的值.如下: 正常的writeup都是写个爬虫,但我觉得burp肯定有自带这种功能,不用重造轮子.经过学习后发现以下步骤可以实现. ...
- Python操作MySQL数据库(步骤教程)
我们经常需要将大量数据保存起来以备后续使用,数据库是一个很好的解决方案.在众多数据库中,MySQL数据库算是入门比较简单.语法比较简单,同时也比较实用的一个.在这篇博客中,将以MySQL数据库为例,介 ...
- 如何使用REDIS进行微服务间通讯
如何使用REDIS进行微服务间通讯 尽可能避免service - to - service通信.为此,需要在服务之间推一个消息队列.回顾一下微服务的概念小型的,非常集中的进程彼此独立运行并且易于维护, ...
- Makefile教程(绝对经典,所有问题看这一篇足够了)【转】
该篇文章为转载,是对原作者系列文章的总汇加上标注. 支持原创,请移步陈浩大神博客: http://blog.csdn.net/haoel/article/details/2886 makefile很重 ...
- GB28181技术基础之1 - SIP协议
SIP 协议,即 会话初始协议(Session Initiation Protocol),是一个应用层的 点对点协议,用于初始.管理和终止网络中的语音和视频会话,是 GB28181 的核心之一. 按照 ...
- 设定rsync开机自启动
1.启用rsync服务systemctl enable rsync 2.打开rsync自己的开关,这个找了好多地方才找到的vi /etc/default/rsyncRSYNC_ENABLE=true
- JS Array.apply会有内存泄漏问题
报错内容: Maximum call stack size exceeded 参考:https://www.jianshu.com/p/b9ba0ddd3392 对象较多,前端JS内存溢出: 数组克隆 ...
- Android点击事件通过kotlin几种实现方式总结
一般来说,Android点击事件通过kotlin有以下几种实现方式: 1.通过全局接口View.OnClickListener实现,代码如下 //class MainActivity : AppCom ...