既然要学习算法,就要学习到它的精髓,才能够使用起来得心应手。

  我还是远远不够啊。

  早就知道,dijkstra 算法可以用优先队列优化,我却一直不知道该怎样优化。当时,我的思路是这样的:假设有n个顶点,将这n个顶点的id和距原点的距离放在结构体内,再将这n个结构体放入优先队列中,堆顶是距源点距离最小的点。每次要更新距离时,仅仅只需要取堆顶的数就可以了。然而,具体要怎样更新堆内各点的距离呢?将堆顶取出,更新后再放回去?这样的话堆顶永远都会是同一个元素了,因为堆顶元素在更新后,还是距离最小的。那么我们可以依次取出堆顶元素,放在结构体数组之内,等待更新完毕后再放回去,那么这样的时间复杂度是2*n,而原先的时间复杂度,也是2*n,这样的优化没有意义,反而还多了一个结构体数组浪费空间。

  如果你也和我的想法一样,那我们真是太有缘分了,看来大家都是蠢的七窍流血的一类人啊,你是不是也和我一样,正在反思自己是不是应该放弃学习算法啊?实际上,在dijkstra里面,有一个十分重要的标记数组,这个标记数组决定了,已经确定了最短距离的点,就不要再次优化了!你明白了吧,想想自己真是蠢呐,竟然忘记如此重要的数组!

  让我们再次思考,是否要将所有没有确定的点全部放入数组呢?

  当然不要,我们只要将刚刚更新过的放进去就行,因为那些没有更新的,肯定不会是路径最短的。那么我们每次都放,就会导致某个节点被放进去很多次了,但是没关系,他们的被放进去的时候,距离是不同的,所以距离大的会沉到底下去,最短路径一定不是他们(对同一节点来说),他们要出推时,我们只处理第一个,以后的一律不处理。这个我们还用一个标记数组来解决。

  代码自己去找吧,https://blog.csdn.net/jobsandczj/article/details/49962557,这个人写得不错,除了码风很丑,加上竟然使用邻接矩阵。。。然后还有book数组定义了没有使用以外,其他的都还行。

  如果你连这些问题都不想面对,或者根本就不想看代码的话,你还是转行吧。

  在此还是贴上自己的模板吧

  这个模板跑起来反而比我原先的代码更慢,我觉得这是邻接表的问题,因为在一开始我用的是啊哈算法的邻接表,而现在用的是vector,再加上可能我在做的那个题太水了,数据量太小,导致优先队列的优势没有发挥出来。

#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
struct node
{
int x;
int s; bool operator<(const node p)const
{
return p.s<s;
}
};
bool book[100];
int dis[100];
const int inf = 2100000000;
int main()
{
vector<int>u[100];
vector<int>w[100];
int n,m;
cin>>n>>m;
int x,y,z;
for(int i=0;i<m;i++){
cin>>x>>y>>z;
u[x].push_back(y);
w[x].push_back(z);
}
fill(dis,dis+n+1,inf);
dis[1]=0;
priority_queue<node>q;
node exa;
exa.x=1;
exa.s=0;
q.push(exa);
while(!q.empty()){
exa=q.top();q.pop();
if(book[exa.x]){continue;}
book[exa.x]=true;
int t=exa.x;
for(int i=0;i<u[t].size();i++){
if(dis[u[t][i]]>dis[t]+w[t][i]){
dis[u[t][i]]=dis[t]+w[t][i];
exa.s=dis[u[t][i]];
exa.x=u[t][i];
q.push(exa);
}
}
}
for(int i=1;i<=n;i++){
cout<<dis[i]<<" ";
}
cout<<endl;
}

  

下面的代码包括了对路径的输出,只是我没有找到这样的题,所以不敢保证算法的正确性:

#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
struct node
{
int x;
int s; bool operator<(const node p)const
{
return p.s<s;
}
};
bool book[100];
int dis[100];
int f[1000];
const int inf = 2100000000;
int main()
{
vector<int>u[100];
vector<int>w[100];
int n,m;
cin>>n>>m;
int x,y,z;
for(int i=0;i<m;i++){
cin>>x>>y>>z;
u[x].push_back(y);
w[x].push_back(z);
}
fill(dis,dis+n+1,inf);
fill(f,f+n+1,-1);
dis[1]=0;
priority_queue<node>q;
node exa;
exa.x=1;
exa.s=0;
q.push(exa);
while(!q.empty()){
exa=q.top();q.pop();
if(book[exa.x]){continue;}
book[exa.x]=true;
int t=exa.x;
for(int i=0;i<u[t].size();i++){
if(dis[u[t][i]]>dis[t]+w[t][i]){
dis[u[t][i]]=dis[t]+w[t][i];
exa.s=dis[u[t][i]];
f[u[t][i]]=t;
exa.x=u[t][i];
q.push(exa);
}
}
}
stack<int>h;
for(int i=1;i<=n;i++){
cout<<dis[i]<<": ";
int ah=f[i]; while(ah!=-1){
h.push(ah);
ah=f[ah];
}
while(!h.empty()){
cout<<h.top()<<" ";
h.pop();
}cout<<i<<" ";
cout<<endl;
}
cout<<endl;
}

  

  每个人都是被动出生,只有选择死亡才是真正的自由!

dijkstra 的优先队列优化的更多相关文章

  1. 地铁 Dijkstra(优先队列优化) 湖南省第12届省赛

    传送门:地铁 思路:拆点,最短路:拆点比较复杂,所以对边进行最短路,spfa会tle,所以改用Dijkstra(优先队列优化) 模板 /******************************** ...

  2. poj 1511 优先队列优化dijkstra *

    题意:两遍最短路 链接:点我 注意结果用long long #include<cstdio> #include<iostream> #include<algorithm& ...

  3. 【bzo1579】拆点+dijkstra优先队列优化+其他优化

    题意: n个点,m条边,问从1走到n的最短路,其中有K次机会可以让一条路的权值变成0.1≤N≤10000;1≤M≤500000;1≤K≤20 题解: 拆点,一个点拆成K个,分别表示到了这个点时还有多少 ...

  4. POJ 1511 Invitation Cards(单源最短路,优先队列优化的Dijkstra)

    Invitation Cards Time Limit: 8000MS   Memory Limit: 262144K Total Submissions: 16178   Accepted: 526 ...

  5. Dijkstra算法(朴素实现、优先队列优化)

    Dijkstra算法只能求取边的权重为非负的图的最短路径,而Bellman-Ford算法可以求取边的权重为负的图的最短路径(但Bellman-Ford算法在图中存在负环的情况下,最短路径是不存在的(负 ...

  6. dijkstra算法之优先队列优化

    github地址:https://github.com/muzhailong/dijkstra-PriorityQueue 1.题目 分析与解题思路 dijkstra算法是典型的用来解决单源最短路径的 ...

  7. 晴天小猪历险记之Hill(Dijkstra优先队列优化)

    描述 这一天,他来到了一座深山的山脚下,因为只有这座深山中的一位隐者才知道这种药草的所在.但是上山的路错综复杂,由于小小猪的病情,晴天小猪想找一条需时最少的路到达山顶,但现在它一头雾水,所以向你求助. ...

  8. 最短路--dijkstra+优先队列优化模板

    不写普通模板了,还是需要优先队列优化的昂 #include<stdio.h> //基本需要的头文件 #include<string.h> #include<queue&g ...

  9. 最短路模板(Dijkstra & Dijkstra算法+堆优化 & bellman_ford & 单源最短路SPFA)

    关于几个的区别和联系:http://www.cnblogs.com/zswbky/p/5432353.html d.每组的第一行是三个整数T,S和D,表示有T条路,和草儿家相邻的城市的有S个(草儿家到 ...

随机推荐

  1. python-批量添加图片水印

    前言: 最近总是被无良公众号和培训机构拷贝文章,他们根本不会给你备注原文出处,这种行为真的让人不高兴,所以计划以后的文章都添加上自己的水印. 话不多说,直接上代码. 一.单张图片添加文字水印 # -* ...

  2. Python-复习-习题-13

    复习 dict: dic = {'name':'alex'}增:dic['age'] = 21 存在就覆盖dic.setdefault() 存在什么也不做,没有就增加 删除:pop()按照key删除, ...

  3. xcode archive 去掉dsym文件和添加dsym文件

    打包慢,让人发狂!!! 所以我们尝试的去掉一些测试时候用不到的东西 比如DSYM: 这DSYM是收集奔溃的.在测试的时候不需要这些东西的所以去掉就好: 项目  Build Settings -> ...

  4. jenkins 上命令各种找不到问题

    代码: 兵马未动,粮草先行 作者: 传说中的汽水枪 如有错误,请留言指正,欢迎一起探讨. 转载请注明出处.   在使用jenkins的时候,会使用一些命令行,有的时候明明在电脑的命令行(终端)可以执行 ...

  5. 2017乌鲁木齐区域赛D题Fence Building-平面图的欧拉公式

    这个题B站上面有这题很完整的分析和证明,你实在不懂,可以看看这个视频  https://www.bilibili.com/video/av19849697?share_medium=android&a ...

  6. "Linux内核分析"第七周

    可执行程序的装载 张文俊+原创作品转载请注明出处+<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.预 ...

  7. <<浪潮之巅>>阅读笔记三

    纵看世界,横看国内.我们国内也有很多很优秀的企业正在走向或者已经处于浪潮之巅.阿里巴巴.腾讯和百度这三巨头应该是我们计算机行业的龙头.但是 不得不说,在创新方面我们做的并不多,这是值得每一个从事计算机 ...

  8. 使用Eclipse可以方便的统计工程或文件的代码行数,

    使用Eclipse可以方便的统计工程或文件的代码行数,方法如下: 1.点击要统计的项目或许文件夹,在菜单栏点击Search,然后点击File... 2.选中正则表达式(Regular expressi ...

  9. Under the same directory(folder) copy or rename with the different extension name

    @echo offsetlocal EnableDelayedExpansionfor /f "delims=" %%i in ('dir *.vm /q/s/b') do ( c ...

  10. [linux学习]sysctl 以及 net.ipv4.ip_forward

    1. sysctl 命令显示 当前系统的参数配置信息 显示全部配置信息 sysctl -a 帮助信息主要如下: [root@k8s-master ~]# sysctl -help Usage: sys ...