首先说下STL优先队列的局限性,那就是只提供入队、出队、取得队首元素的值的功能,而dijkstra算法的堆优化需要能够随机访问队列中某个节点(来更新源点节点的最短距离)。

看似可以用vector配合make_heap/push_heap/pop_heap来实现这个功能,实际上手动实现就会发现问题所在。比如在dist[v] > dist[u] + cost(u,v)时,需要更新dist[v],然后重新确定v在vector的位置,需要使用push_heap,这样问题就出现了。

v又在vector的哪个位置呢?只有在vector中一个个查找,除非在之前维护最小(距离)堆的时候,每次交换元素,记录元素的位置变化,也就是用int pos[V];(V为顶点数,下面不再重复说明)来记录,每次push_heap和pop_heap使堆的元素交换的时候(swap(heap[i], heap[j];)还要顺便交换位置(swap(pos[i], pos[j]);)

而仅仅是用STL提供的接口是无法实现的,只有从头造轮子。

于是有个折中的方法,那就是仍然使用优先队列。只是在更新点v的最短距离时,把点v重新加入队列中,而队列中已经存在的v无法访问就继续搁着。

也就是说队列中有2个点v,一个是用更新后的距离进行堆操作的,一个是用更新前的距离进行堆操作的。

首先我不是用while (!q.empty())判断终止条件的,而是照着书上的for (int i = 0; i < V; i++)判断,这样问题就在于,可能点v已经出队了(代表着已经确定源点到点v的最短路径),此时若点v出队则需要跳过。

书上之所以只循环V-1次是因为书上用的堆优化,不会像我这样重复添加某元素到堆中,而是更新堆中元素的权值并移动位置。由于每次循环都能确定源点到某个点的最短路径,所以只需要V-1次足矣。

而退而求其次的直接用优先队列的做法也可以直接循环V-1次,只不过每次循环开头要判断队首元素是否已经确定了最短距离,若是则弹出,一直到队首元素是未确定最短距离。不如while (!q.empty())加continue简洁(见下面核心代码)

auto comp = [](int v1, int v2) { return dist[v1] > dist[v2]; };
priority_queue<int, vector<int>, decltype(comp)> q(comp);
dist[v0] = 0;
q.push(v0); while (!q.empty()) {
int u = q.top();
q.pop();
if (vis[u]) // 已经求过v0到u的最短路径
continue; vis[u] = true;
for (auto& e : adjList[u]) {
int v = e.adjID;
if (!vis[v] && dist[v] - dist[u] > e.len) {
dist[v] = dist[u] + e.len;
pre[v] = u;
q.push(v);
}
}
}

其他代码就不贴了,对其中用到的一些全局变量做个说明。

注意如果dist是定义在dijkstra函数体内的,lambda表达式要捕获dist的引用,即auto comp = [&dist](后面不变)

vector<AdjList> adjList;  // 邻接表, 预先读取了数据
// AdjList是STL容器Container<T>的别名(Container可以是vector或list或deque),T是AdjEdge(邻接边), 定义如下(省略了构造函数)
struct AdjEdge {
int adjID; // 邻接点的ID
int len; // 邻接边的长度
};
vector<int> dist(V, INT_MAX); // 最短距离
vector<int> pre(V, -1); // 最短路径上的前1个节点号
deque<bool> vis(V, false); // 若求出了最短距离则置为true

基于STL优先队列和邻接表的dijkstra算法的更多相关文章

  1. 邻接表实现Dijkstra算法以及DFS与BFS算法

    //============================================================================ // Name : ListDijkstr ...

  2. 做了一道跑大数据的最短路挂了,基于vector的二维模拟邻接表实现Dijkstra算法(*【模板】)

    代码: #include <stdio.h> #include <string.h> #include <string> #include <vector&g ...

  3. C++ 基于STL的演讲比赛流程管理系统(sort算法+小型算法(accumulate)+内建函数对象+string字符串拼接+字符串截取+多个容器基础操作+与用户交互+文件的读写+保存+重建+整体文件数据的清空)

    1 /* 2 比赛规则: 3 学校举行一演讲比赛,共12个人参加,比赛两轮,第一轮为淘汰赛 第二轮为决赛 4 每名选手都有对应的编号:如10001~10012 5 比赛方式:分组比赛 每组6人 6 第 ...

  4. POJ 1511 Invitation Cards(Dijkstra(优先队列)+SPFA(邻接表优化))

    题目链接:http://poj.org/problem?id=1511 题目大意:给你n个点,m条边(1<=n<=m<=1e6),每条边长度不超过1e9.问你从起点到各个点以及从各个 ...

  5. 基于STL的字典生成模块-模拟搜索引擎算法的尝试

    该课题来源于UVA中Searching the Web的题目:https://vjudge.net/problem/UVA-1597 按照题目的说法,我对按照特定格式输入的文章中的词语合成字典,以满足 ...

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

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

  7. 最小生成树Prim算法(邻接矩阵和邻接表)

    最小生成树,普利姆算法. 简述算法: 先初始化一棵只有一个顶点的树,以这一顶点开始,找到它的最小权值,将这条边上的令一个顶点添加到树中 再从这棵树中的所有顶点中找到一个最小权值(而且权值的另一顶点不属 ...

  8. 第6章 图的学习总结(邻接矩阵&邻接表)

    我觉得图这一章的学习内容更有难度,其实图可以说是树结构更为普通的表现形式,它的每个元素都可以与多个元素之间相关联,所以结构比树更复杂,然而越复杂的数据结构在现实中用途就越大了,功能与用途密切联系,所以 ...

  9. 最短路径 | 深入浅出Dijkstra算法(一)

    参考网址: https://www.jianshu.com/p/8b3cdca55dc0 写在前面: 上次我们介绍了神奇的只有五行的 Floyd-Warshall 最短路算法,它可以方便的求得任意两点 ...

随机推荐

  1. 【zznu-夏季队内积分赛3-F】学无止境

    题目描述 “别人总说我瓜,其实我一点也不瓜,大多数时候我都机智的一批“ACM程序设计竞赛是一个团体项目.宝儿姐作为其中优秀的一份子,每天好好学习天天向上.曾经宝儿姐给自己定了一个计划,刷穿bzoj.于 ...

  2. sql 日志统计-日、周、月活跃数

    近日网站需求:统计日志表的 日.周.月活跃数.最终研究了出来了,分享给大家看下.  如果有更好的sql语句也可以评论下方. --日活跃量 ), cr.AddTime, )as addtimt,COUN ...

  3. LeetCode OJ:Search in Rotated Sorted Array(翻转排序数组的查找)

    Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 6 7 migh ...

  4. TableviewCell嵌套TextView自动换行

    TableviewCell嵌套TextView自动换行 欢迎到github上去下载源码Demo, github链接:https://github.com/mengzhihun6 效果图:

  5. C++中几个值得分析的小问题(2)

    下面有3个小问题,作为C++ Beginner你一定要知道错在哪里了. 1.派生类到基类的引用或指针转换一定“完美”存在? 一般情况,你很可能会认为:派生类对象的引用或指针转换为基类对象的引用或指针是 ...

  6. 记用ajax网页跳转大坑——后台执行了,但是没有跳转

    搭建javaweb服务器的时候,把jsp文件放在WEB-INF目录下面,因为超链接不能所有只能通过拦截器,用do方法跳转 controller写的是对的: @Controller public cla ...

  7. New Concept English three (23)

    31w 45 People become quite illogical when they try to decide what can be eaten and what cannot be ea ...

  8. New Concept English three(17)

    27W/m 65 Verrazano, an Italian about whom little is known, sailed into New York Harbour in 1524 and ...

  9. kafka--linux环境搭建

    1.JDK 1.8 2.zookeeper 3.4.8 解压 3.kafka 配置 在kafka解压目录下下有一个config的文件夹,里面放置的是我们的配置文件 consumer.properite ...

  10. 软件测试模型---V模型、W模型、H模型、X模型

    人活着一定要有目标,确定自己喜欢什么,再坚持做下去,那么他过得一定不会太差. 煽情的话,不多说,本文主要讲解:"软件测试模型-V模型.W模型.H模型.X模型". 1.V模型 V模型 ...