题目链接 : 点击查看

题目描述

给定一个 n 个点 m 条边的有向图,图中可能存在重边和自环,所有边权均为非负值。

请你求出 1 号点到 n 号点的最短距离,如果无法从 1 号点走到 n 号点,则输出 −1。

输入输出格式

输入

第一行包含整数 n 和 m。
接下来 m 行每行包含三个整数 x,y,z,表示存在一条从点 x 到点 y 的有向边,边长为 z。

输出

输出一个整数,表示 1 号点到 n 号点的最短距离。
如果路径不存在,则输出 −1。

输入输出样例

输入

3 3
1 2 2
2 3 1
1 3 4

输出

3

题目分析

本题我们用堆优化版的dijkstra来解。堆优化版的dijkstra算法与SPFA算法的写法有些类似,但两者之间的算法思想不同。SPFA算法实质上是一种动态逼近法,用队列来实现,每次加入队列的点是松弛之后可以更新最短距离的点,每个点通过其前驱节点来更新到源点最短路,实现动态逼近,且SPFA算法中的st[i]状态数组标记的是i点是否在队列中。而堆优化版的dijkstra是通过堆来确定每一次遍历距离源点最短距离的点,将此点的st[i]赋值为true,意为此点为已经找到最短路径的点,其他部分与朴素dijkstra算法相同。

关于堆,其节点的数据类型为pair<int, int> 类型,第一个值为最短距离,第二个值为相应的点,且在此我们建立的是小根堆,堆顶元素为当前遍历层数下,距离源点最小距离的点(每一次遍历堆顶元素都是距离前一个点的最短距离,贪心叠加即为距离源点的最短距离)。我们先将{0,1}入队,作为heap的初始化,1为图的源点,0是1到1的距离。然后对heap进行遍历,每一次取出堆顶元素t,然后遍历与堆顶元素所对应的点t.second有直接边相连的所有点(在此图我们用邻接表来存储,即为遍历以t.second为头结点的邻接表),然后我们判断每一个与其相连的点是否可以通过t.second为中间点进行松弛操作,来缩短与源点的距离,如可以,我们将这个点,和松弛之后的最短距离压入堆中。由此可见,堆中维护的是可能为最短路的点和相应的最短路径,且由于是pair<int, int> 类型,heap首先按照第一关键字进行排序,其次在按照第二关键字进行排序,因此堆顶的点一定是最小距离的点,若是每个点在堆中存有多个路径(即第一关键字不同,第二关键字相同),每一点对应的第一个元素下的距离即为当前遍历层数下此点距离源点的最短距离(如不是堆顶元素则不一定是最终的最短距离,是相应遍历层数下的最短距离)。详见如下代码。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<functional>
using namespace std;
typedef pair<int, int> PII;
const int N = 1e5 + 5e4 + 7;
int h[N], e[N], ne[N], cur;
int w[N];
int dist[N];
bool st[N];
int n, m;
void add(int v1, int v2, int c) {w[cur] = c;e[cur] = v2;ne[cur] = h[v1];h[v1] = cur ++ ;
}
int dijkstra() {memset(dist, 0x3f, sizeof(dist));dist[1] = 0;priority_queue <PII, vector<PII>, greater<PII>> heap;//priority_queue<Type, Container, Functional>Type是比较类型,Container是容器类型,Funcitonal是比较方式 heap.push({0, 1});//heap在此是小根堆 维护最短距离 while (heap.size()) {PII k = heap.top();heap.pop();int v = k.second, distance = k.first;if (st[v]) continue;st[v] = true;for (int i = h[v]; 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;else return dist[n];
}
int main() {memset(h, -1, sizeof(h));cin >> n >> m;while (m -- ) {int v1, v2, w;cin >> v1 >> v2 >> w;add(v1, v2, w);}cout << dijkstra() << endl;return 0;
}

在此我们给出堆优化版的dijkstra的模板

时间复杂度 O(mlogn), n 表示点数, m 表示边数, 适用于稀疏图
ypedef pair<int, int> PII;int n;      // 点的数量
int h[N], w[N], e[N], ne[N], idx;       // 邻接表存储所有边
int dist[N];        // 存储所有点到1号点的距离
bool st[N];     // 存储每个点的最短距离是否已确定// 求1号点到n号点的最短距离,如果不存在,则返回-1
int dijkstra()
{memset(dist, 0x3f, sizeof dist);dist[1] = 0;priority_queue<PII, vector<PII>, greater<PII>> heap;heap.push({0, 1});      // first存储距离,second存储节点编号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];
}

AcWing 850. Dijkstra求最短路 II(堆优化dijkstra)相关推荐

  1. AcWing 850. Dijkstra求最短路 II【最短路】【堆优化版Dijkstra】

    AcWing 850. Dijkstra求最短路 II 一.题目链接 二.题目分析 (一)算法标签 (二)解题思路 三.AC代码 四.其它题解 一.题目链接 AcWing 850. Dijkstra求 ...

  2. 堆优化版dijkstra算法:AcWing 850. Dijkstra求最短路 II

    堆优化版dijkstra算法分析: 朴素版dijkstra的时间复杂度为O(n^2),主要瓶颈在于第1步的寻找全局最小值的过程. 可以用小根堆(C++STL priority_queue)对dist数 ...

  3. AcWing 850. Dijkstra求最短路 II

    原题链接:AcWing 850. Dijkstra求最短路 II 给定一个 n 个点 m 条边的有向图,图中可能存在 重边 和 自环 ,所有边权均为 非负值 . 请你求出 1 号点到 n 号点的最短距 ...

  4. Dijkstra AcWing 850. Dijkstra求最短路 II

    Dijkstra AcWing 850. Dijkstra求最短路 II 原题链接 AcWing 850. Dijkstra求最短路 II 算法标签 最短路 Dijkstra 思路 图片摘自该题解 图 ...

  5. AcWing 850. Dijkstra求最短路 II(最短路)

    堆优化dijkstra: #include<bits/stdc++.h> using namespace std;const int N=200010; typedef pair<i ...

  6. 【ACWing】850. Dijkstra求最短路 II

    题目地址: https://www.acwing.com/problem/content/description/852/ 给定一个nnn个点mmm条边的有向图,图中可能存在重边和自环,所有边权均为非 ...

  7. 850. Dijkstra求最短路 II

    堆优化的步骤 1.用一个优先队列来存储编号和距离 2.对求出已知点中的最短距离来更新每一个点 3.判断是否有解 代码 #include <cstring> #include <ios ...

  8. Dijkstra求最短路 II

    给定一个n个点m条边的有向图,图中可能存在重边和自环,所有边权均为正值. 请你求出1号点到n号点的最短距离,如果无法从1号点走到n号点,则输出-1. 输入格式 第一行包含整数n和m. 接下来m行每行包 ...

  9. dij算法堆优化_BZOJ 3040 最短路(road) 堆优化Dijkstra | 学步园

    题目大意:最短路. 思路:最短路. 贴一份比较高效的堆优化Dij模板吧. CODE: #include #include #include #include #define _MAX 1000010 ...

最新文章

  1. CentOS 5.1下安装Opensim
  2. [Android1.6]继承BaseAdapter为GridView设置数据时设置setLayoutParams时注意
  3. thinkphp路由配置 php7.0,thinkphp3.2 路由设置方法
  4. 2019ICPC(南昌) - Fire-Fighting Hero(最短路+思维)
  5. 纯CSS将图片转换成黑白
  6. 软件体系架构课下作业07
  7. C/C++ 结构体成员在内存中的对齐规则(转载)
  8. 卡片书签——简洁的 Chrome 书签扩展
  9. 基于freemarker生成pdf
  10. UI自动化 win32 模拟键盘按键
  11. Pascal到c++,求大佬翻译!
  12. 如何将一个服务器加入域控中,Windows Server如何创建域并加入域
  13. java错误找不到符号怎么办_java错误找不到符号
  14. 2017年囧事大全,全部真人真事
  15. ESP8266串口WIFI 无线控制模块
  16. 耗时5小时用纯HTML和CSS写成的博学谷
  17. 1.1.24 制作红头文件
  18. swal()弹出删除确认框
  19. 软件测试 | 测试开发 | 测试开发基础|一文搞定计算机网络(一)
  20. 三菱mr服务器如何显示脉冲数,MR-JE-200A参数设置三菱MR-JE-200A操作手册(故障排除篇) - 广州正凌...

热门文章

  1. 23岁前的21条忠告
  2. XDCTF2014 Writeup
  3. 2017-7-10 暑期实训日志
  4. ernieSAGE:PGL at TextGraphs 2020 Shared Task: Explanation Regeneration using Language and Graph Lear
  5. C语言用pthread.h创建线程
  6. 订单管理-格式化日期-HTML
  7. 【爬虫】批量爬取免费简历模板
  8. excel超链接应用:快速生成目录的几个方法-上
  9. 浙江大学计算机招生录取线,北大清华浙大的录取分数线都是多少?2021浙江高考招生普通类,首段平行志愿今天投档...
  10. Javascript 面向对象编程(一):封装 ——转自阮一峰博客