Dijkstra迪杰斯特拉+堆优化

众所周知,朴素的迪杰斯特拉的时间复杂度为O(n^2),这在某些题目当中是会超时的。但如果在迪杰斯特拉中枚举每个最短边时加入堆优化,则迪杰斯特拉的效率则会大大提高。

朴素版迪杰斯特拉

void dijkstra(int x)  //x为起点,使用迪杰斯特拉查找起点到其他任意点的最短路径
{for(int i = 1; i <= n; i++) dis[i] = w[x][i];  //dis[i]数组存储从x到i的最短路(迪杰斯特拉跑完之前不一定是最终解)//w[i][j]数组存储从i到j的路径长度(这里用的邻接矩阵存储,也可以换成前向星等)b[x] = 1; //b[i]数组存储此点是否被访问过dis[x] = 0;for(int i = 1; i <= n - 1; i++){minl = maxx;k = 0;for(int j = 1; j <= n; j++)  //查找可以更新的点if((!b[j]) && (dis[j] < minl)){minl = dis[j];k = j;}if(k == 0) break;  //这一句也可以换成if(k == y) break;表示已经更新完从x到y的最短路b[k] = true;  //更新k点,把k标记为已确定最短路径for(int j = 1; j <= n; j++)  //更新与k相连的每个未确定最短路径的顶点jif(dis[k] + w[k][j] < dis[j])dis[j] = dis[k] + w[k][j]; //可以加上pre[j] = k用来记录前驱节点}
}

加入堆优化

笔者在oj上找到了几个较好的不同类型的模板,大家可以灵活选择记忆理解。

题目

题目描述

如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度。

输入输出格式

输入格式:
第一行包含三个整数N、M、S,分别表示点的个数、有向边的个数、出发点的编号。

接下来M行每行包含三个整数Fi、Gi、Wi,分别表示第i条有向边的出发点、目标点和长度。

输出格式:
一行,包含N个用空格分隔的整数,其中第i个整数表示从点S出发到点i的最短路径长度(若S=i则最短路径长度为0,若从点S无法到达点i,则最短路径长度为2147483647)
输入输出样例
输入样例#1:

4 6 1
1 2 2
2 3 2
2 4 1
1 3 5
3 4 3
1 4 4

输出样例#1:

0 2 4 3

版本一(邻接矩阵存图)

#include<vector>
#include<map>
#include<queue>
#include<algorithm>
#include<set>
#include<iostream>
#include<cstdio>
#include<list>
#include<string>
#include<cmath>
#include<cstring>
#include<stack>
using namespace std;
struct ha//小根堆
{int x; int d;//节点编号 bool operator < (const ha &a) const {return x > a.x;}
};
struct haha//小根堆
{int x; int d;//节点编号
};
ha e;
haha ee;
int d[1000010];
priority_queue <ha> q;
int n, m, s, xx, yy, zz, i;
vector<haha> a[1000000];
int main()
{scanf("%d%d%d",&n ,&m ,&s);for(i = 1; i <= m; i++){scanf("%d%d%d",&xx ,&yy ,&zz);ee.d = yy;ee.x = zz;a[xx].push_back(ee);}for(i = 1; i <= n; i++) d[i] = 2000003647;e.d = s;e.x = 0; d[s] = 0;q.push(e);//入队 while (!q.empty())//队列非空 {e = q.top(); q.pop();//出队int v = e.d;//取出节点编号int d1 = e.x;if (d[v] < d1) continue;//说明在这个点再此之后又入队了//此次出队的并不是s到这个点的最短路,//所以在这次更新前点v所连的点已经更过一次了 //所以后面也不会进行松弛操作 int len = a[v].size(); for(i = 0; i < len; i++){haha g = a[v][i];if ((d[v] + g.x < d[g.d]) || (d[g.d] == -233))//松弛操作 {d[g.d] = d[v] + g.x;e.d = g.d;e.x = d[g.d];q.push(e);}}}for (i=1; i <= n; i++) //输出 if (d[i] == 2000003647) cout << 2147483647 << " "; else cout << d[i] << " ";return 0;
}

版本二(前向星存图)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int INF = 2147483647;
const int maxn = 10000 + 10;
const int maxm = 500000 + 10;
int n, m, s;
int fir[maxn], nxt[maxm], to[maxm], val[maxm], cnt;
void add_edge(int u, int v, int w) //前向星加边
{nxt[++cnt] = fir[u];fir[u] = cnt;to[cnt] = v;val[cnt] = w;
}
struct Node
{int d, id;Node(){}Node(int d, int id) : d(d), id(id){}bool operator < (const Node& rhs) const{return d > rhs.d;//重载 < 方便堆}
};
int dis[maxn], vis[maxn];
void Dijkstra(int s)
{for(int i = 1; i <= n; i++) dis[i] = INF;dis[s]=0;priority_queue<Node> Q;Q.push(Node(0,s));while(!Q.empty()) {Node u = Q.top(); Q.pop();if(vis[u.id]) continue;  //若某个点已经被更新到最优,就不用再次更新其他点vis[u.id] = 1;for(int e = fir[u.id]; e; e = nxt[e]) {int v = to[e], w = val[e];if(u.d + w < dis[v]) {dis[v] = u.d + w;Q.push(Node(dis[v],v));}}}
}
int main()
{scanf("%d%d%d",&n ,&m ,&s);for(int u, v, w, i=0; i < m; i++){scanf("%d%d%d",&u ,&v ,&w);add_edge(u, v, w);}Dijkstra(s);for(int i = 1; i <= n; i++) printf("%d ", dis[i]);return 0;
}

版本三(运用pair存储)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<utility>
#include<vector>
#include<queue>
#define MAXN 20000
#define INF 2147483647
using namespace std;
typedef pair<int,int> pii;
priority_queue<pii, vector<pii>, greater<pii> > pq;
struct edge
{int to;int cost;
};
vector<edge> G[MAXN];//g[i]--i to g[i].to cost cost
int n, m, s;
int dis[MAXN];
void dijk(int s)
{for(int i = 1; i <= n; i++)dis[i] = INF;dis[s] = 0;pq.push(make_pair(0,s));// cout<<dis[s]<<endl;while(!pq.empty()){pii u = pq.top();pq.pop();int x = u.second; // bian hao//cout<<x<<endl;for(int i = 0; i < G[x].size(); i++){edge e = G[x][i];if(dis[e.to] > dis[x] + e.cost){dis[e.to] = dis[x] + e.cost;pq.push(make_pair(dis[e.to], e.to));// cout<<dis[e.to]<<endl;}}}
}
int main()
{cin >> n >> m >> s;int from, to, cost;edge in;for(int i = 0; i < m; i++){scanf("%d%d%d",&from ,&to ,&cost);in.to = to; in.cost = cost;G[from].push_back(in);}// cout<<endl;dijk(s);for(int i = 1; i <= n; i++)printf("%d ", dis[i]);return 0;
}

【讲解 + 模板】Dijkstra迪杰斯特拉+堆优化相关推荐

  1. 7-38 社交网络图中结点的“重要性”计算 (30分) 最短路 迪杰斯特拉堆优化

    在社交网络中,个人或单位(结点)之间通过某些关系(边)联系起来.他们受到这些关系的影响,这种影响可以理解为网络中相互连接的结点之间蔓延的一种相互作用,可以增强也可以减弱.而结点根据其所处的位置不同,其 ...

  2. 通往奥格瑞玛的道路(二分+迪杰斯特拉堆优化)

    题目背景 在艾泽拉斯大陆上有一位名叫歪嘴哦的神奇术士,他是部落的中坚力量 有一天他醒来后发现自己居然到了联盟的主城暴风城 在被众多联盟的士兵攻击后,他决定逃回自己的家乡奥格瑞玛 题目描述 在艾泽拉斯, ...

  3. Dijkstra(迪杰斯特拉)模板

    Dijkstra(迪杰斯特拉) 算法思想 本质来说是一种贪心.每次选择一条最短路径,这样最后得到的就是一条最短路径. 举个例子: 代码模板(邻接表与邻接矩阵) 邻接矩阵版 #include <i ...

  4. 【迪杰斯特拉的优化】 洛谷4779板子题

    P4779 [模板]单源最短路径(标准版) 题目背景 2018 年 7 月 19 日,某位同学在 NOI Day 1 T1 归程 一题里非常熟练地使用了一个广为人知的算法求最短路. 然后呢? 最终,他 ...

  5. 图论最短距离(Shortest Path)算法动画演示-Dijkstra(迪杰斯特拉) 和 Floyd(弗洛伊德)

    视 频 地 址 : https://www.bilibili.com/video/BV1q4411M7r9?from=search&seid=16626092504824296903 Dijk ...

  6. JavaScript实现dijkstra迪杰斯特拉算法(附完整源码)

    JavaScript实现dijkstra迪杰斯特拉算法 PriorityQueue完整源代码 MinHeap.js完整源代码 Heap.js完整源代码 Comparator.js完整源代码 dijks ...

  7. C++实现Dijkstra(迪杰斯特拉)算法(附完整源码)

    C++Dijkstra迪杰斯特拉算法的实现 C++Dijkstra(迪杰斯特拉)算法的完整源码(定义,实现,main函数测试) C++Dijkstra(迪杰斯特拉)算法的完整源码(定义,实现,main ...

  8. C语言实现Dijkstra(迪杰斯特拉)算法(附完整源码)

    Dijkstra迪杰斯特拉 Graph结构体定义 迪杰斯特拉算法完整源码(定义,实现,main函数测试) Graph结构体定义 struct Graph {int vertexNum;int **ed ...

  9. Dijkstra迪杰斯特拉算法 C++实现

    本篇文章主要介绍了Dijkstra迪杰斯特拉算法的C++实现,文章包含两个部分,在第一部分中我会简单介绍迪杰斯特拉算法以及一些个人的理解,第二部分会对C++代码的逻辑进行解释.下面是我已经上传的代码资 ...

最新文章

  1. UA MATH571B 试验设计III 单因素试验设计2
  2. 当你从事不喜欢的事怎么办
  3. idea maven创建java项目_新版本IntelliJ IDEA 构建maven,并用Maven创建一个web项目(图文教程)...
  4. java 视图解析器_SpringMVC——视图和视图解析器
  5. Rsync+inotify   组合使用同步方案
  6. 最简单易懂的C语言代码实现最小二乘法线性拟合直线
  7. 163 镜像源 linux,网易163的Ubuntu apt镜像源
  8. 计算机管理 网络连接服务,WZC服务未开启无法连接网络 解决方法及步骤
  9. ​关于技术变现的几点思考
  10. “前首富”牟其中:欠的人情太多,要留着命来还
  11. 这一年,CyberMiles曾经走过的路
  12. golang实现微信公众号发红包功能
  13. Rails中的使用者验证:Devise
  14. VM的三种网络连接方式
  15. 如何在Office 2013或2016中带回Microsoft Office Picture Manager
  16. 免费使用chatgpt的网站集合:
  17. 关于Linux下通过ping/mtr 长期监控网络输出日志报告的一些笔记
  18. My Chief My Regiment(最后续语)
  19. 邬江兴-拟态计算与拟态安全
  20. 怎么将PDF图纸转换成CAD图纸

热门文章

  1. python3中利用serial模块实现单片机与python上位机的通信(串口调试助手)
  2. 记录C语言学习【单个按键之长按+短按】
  3. lpop 原子_深圳大学张文静教授团队ACS Nano:单原子铂修饰的二硫化钒催化剂提高电催化析氢性能...
  4. ERROR: Cannot install keras==2.2.0 and tensorflow==1.14.0 because these package versions have confli
  5. jquery获取ip地址
  6. BurpSuite实战十九之XSS检测实战
  7. URL末尾是否应该加斜杠?
  8. 不用聚合函数求最高工资
  9. ionic的生命周期
  10. 电子制作——锂电池大功率充电器