YY引言

在NOI2018D1T1中出现了一些很震惊的情况,D1T1可以用最短路解决,但是大部分人都在用熟知的SPFA求解最短路。而SPFA的最坏复杂度能够被卡到$O(VE)$。就是边的数量乘以点的数量,而用SPFA的各位都被恶意数据卡成了最坏情况。100->60。这显然很不划算。是时候祭出我们的堆优化$dijkstra$了。

核心思想

朴素的dijkstra的核心是一个贪心的过程。每次找当前已知权值的最小的边来进行松弛。但是每次找的过程中都要用$O(m)$的时间。这样很慢。时间复杂度是$O((m+n)n)$。这显然不是我们想要的结果。小根堆的特性是保证堆顶的数是最小的数,所以我们可以用小根堆来替换贪心找最小权值的过程。而使用了小根堆之后的$dijkstra$算法的时间复杂度就变成了$O((m+n)\log n)$,而且很稳定。

代码实现

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue> using namespace std; typedef pair<long long, int> P;
const int maxedge = 2e5+3;
const int maxnode = 1e5+3;
priority_queue<P, vector<P>, greater<P> > Q;
int fir[maxnode], nx[maxedge], u[maxedge], v[maxedge], w[maxedge];
int dis[maxnode], n, m, s;
bool book[maxnode];
inline int read() {
int x = 0, f = 1; char c = getchar();
while (c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
while (c <= '9' && c >= '0') {x = x*10 + c-'0'; c = getchar();}
return x * f;
} int main() {
n = read(), m = read(), s = read();
memset(fir, -1, sizeof(fir));
fill(dis+1, dis+1+n, 2147483647);
for(int i=1; i<=m; i++) {
u[i] = read(), v[i] = read(), w[i] = read();
nx[i] = fir[u[i]];
fir[u[i]] = i;
}
dis[s] = 0;
Q.push(P(0, s));
while (!Q.empty()) {
P x = Q.top();
Q.pop();
if(x.first > dis[x.second])
continue;
int k = fir[x.second];
while (k != -1) {
if(x.first + w[k] < dis[v[k]]) {
dis[v[k]] = w[k] + x.first;
Q.push(P(dis[v[k]], v[k]));
}
k = nx[k];
}
}
for(int i=1; i<=n; i++) printf("%d ", dis[i]);
}

  

模板题目

Luogu P4779,这个题卡SPFA

Luogu P3371,这个题不卡SPFA

关于dijkstra的小根堆优化的更多相关文章

  1. dijkstra算法的堆优化

    普通的dijkstra算法模板: //数据结构 int g[LEN][LEN]; //邻接矩阵 int vis[LEN]; //标记是否访问 int dist[LEN] //源点到各点的距离 fill ...

  2. 单源最短路径:Dijkstra算法(堆优化)

    前言:趁着对Dijkstra还有点印象,赶快写一篇笔记. 注意:本文章面向已有Dijkstra算法基础的童鞋. 简介 单源最短路径,在我的理解里就是求从一个源点(起点)到其它点的最短路径的长度. 当然 ...

  3. 【Luogu P4779】dijkstra算法的堆优化

    Luogu P4779 利用堆/优先队列快速取得权值最小的点. 在稠密图中的表现比SPFA要优秀. #include<iostream> #include<cstdio> #i ...

  4. POJ-2387.Til the Cows Come Home.(五种方法:Dijkstra + Dijkstra堆优化 + Bellman-Ford + SPFA + Floyd-Warshall)

    昨天刚学习完最短路的算法,今天开始练题发现我是真的菜呀,居然能忘记邻接表是怎么写的,真的是菜的真实...... 为了弥补自己的菜,我决定这道题我就要用五种办法写出,并在Dijkstra算法堆优化中另外 ...

  5. 手写堆优化dijkstra

    \(dijkstra\) 算法的堆优化,时间复杂度为\(O(n+m)\log n\) 添加数组\(id[]\)记录某节点在堆中的位置,可以避免重复入堆从而减小常数 而这一方法需要依托手写堆 #incl ...

  6. 单源最短路问题--朴素Dijkstra & 堆优化Dijkstra

    许久没有写博客,更新一下~ Dijkstra两种典型写法 1. 朴素Dijkstra     时间复杂度O(N^2)       适用:稠密图(点较少,分布密集) #include <cstdi ...

  7. POJ 2502 - Subway Dijkstra堆优化试水

    做这道题的动机就是想练习一下堆的应用,顺便补一下好久没看的图论算法. Dijkstra算法概述 //从0出发的单源最短路 dis[][] = {INF} ReadMap(dis); for i = 0 ...

  8. BZOJ 3040 最短路 (堆优化dijkstra)

    这题不是裸的最短路么?但是一看数据范围就傻了.点数10^6,边数10^7.这个spfa就别想了(本来spfa就是相当不靠谱的玩意),看来是要用堆优化dijkstra了.但是,平时写dijkstra时为 ...

  9. Dijkstra算法的二叉堆优化

    Dijkstra算法的二叉堆优化 算法原理 每次扩展一个距离最小的点,再更新与其相邻的点的距离. 如何寻找距离最小的点 普通的Dijkstra算法的思路是直接For i: 1 to n 优化方案是建一 ...

随机推荐

  1. mysql default null empty string concat varchar text

    text不可设置默认值 null  empty string   前者update 初始值时 我响应,但不报错

  2. poj 1459 多源汇网络流 ISAP

    题意: 给n个点,m条边,有np个源点,nc个汇点,求最大流 思路: 超级源点把全部源点连起来.边权是该源点的最大同意值: 全部汇点和超级汇点连接起来,边权是该汇点的最大同意值. 跑最大流 code: ...

  3. 关于Time Series Database

    今天观察了下clojure之父datomic.com的数据库 有点类似sequence数据库的变种 不过这类数据库,感觉用在移动端会更有市场: 1. 移动端需要这种可以本地存储,无删除,联网只增加,只 ...

  4. IDEA 的使用(快捷键、括号对齐的方式)

    Java IDE 工具不是只有一个 Eclipse,还有同样十分优秀的 IDEA. 0. 常用快捷键 查看与设置:[File]⇒ [Settings]⇒ [Keymap] back/forward:c ...

  5. 杂项-Java:FreeMarker

    ylbtech-杂项-Java:FreeMarker 1.返回顶部 1. FreeMarker是一款模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页.电子邮件.配置文件.源 ...

  6. IDEA kafka producer数据输出缓慢 和 kafka consumer 报错的处理

    问题1. IDEA 中Kafa_Producer程序数据输出缓慢 但不报错 问题2. Kafa_Consumer程序报错: 17/11/10 11:31:11 ERROR ReceiverTracke ...

  7. easyui图标对照

    转自:https://blog.csdn.net/qq_34545192/article/details/78250816 原作者文章地址: http://www.cnblogs.com/timeme ...

  8. E2017614-hm

     pluck   n. 勇气,精神; 内脏; 快而猛的拉; 〈俚〉不及格;   vt. 拔掉; 采,摘; 鼓起(勇气等); 弹(乐器);  scope  n. (处理.研究事务的) 范围; 眼界,见识 ...

  9. Sql 主键设置

    1.开发数据库时常用命名规范 1>.使用不包含数字的单数表名,如果必要的话可以增加模块名前缀. 2>.对于主键的命名,使用表名+ID的形式. 3>.作为外键的列的名字应该与它们所对应 ...

  10. JavaScript--DOM访问子结点childNodes

    访问子结点childNodes 访问选定元素节点下的所有子节点的列表,返回的值可以看作是一个数组,他具有length属性. 语法: elementNode.childNodes 注意: 如果选定的节点 ...