版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/Mashiro_ylb/article/details/78287724

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用来记录前驱节点}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

加入堆优化

笔者在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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74

版本二(前向星存图)

#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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62

版本三(运用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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61

* Dijkstra 堆优化相关推荐

  1. dijkstra堆优化(multiset实现-大大减小代码量)

    例题: Time Limit: 1 second Memory Limit: 128 MB [问题描述] 在电视时代,没有多少人观看戏剧表演.Malidinesia古董喜剧演员意识到这一事实,他们想宣 ...

  2. A - Age of Moyu HDU - 6386(Dijkstra+堆优化)

    要解决这道题,可以用dfs+bfs,但是我不会,所以我只会dijkstra算法: 要解决这道题必须明白迪杰斯特拉算法的核心思想,我是这样理解的: 我可以任意举例一个图: 比如这个图,那么求1-6的最短 ...

  3. poj1511 InvitationCards 最短路 Dijkstra堆优化

    第一反应想到和 poj3268做法一样,先是从起点dj,然后将图反向,再次dj一次,求和即可.但是,数据O(n*n)过不去,所以需要使用dijkstra的堆优化! 淦,没用scanf结果超时了= = ...

  4. 寒假集训 最短路(I - Heavy Transportation)dijkstra+堆优化

    今天的集训学习了最短路dijkstra的堆优化,把时间复杂度从朴素版的O()降至了O(n*logn+m). 首先,先上一段朴素版的代码. void dijkstra() {dist[1] = 0;fo ...

  5. dijkstra+堆优化

    分析: 可知Dijkstra算法的复杂度是O(n*n) Dijkstra算法在寻找集合T中距离最小的顶点W(即寻找dist数组中最小值)复杂度是O(n),在更新距离操作时复杂度为O(n). 上述操作需 ...

  6. HDU-6290 奢侈的旅行 2018女赛 Dijkstra堆优化

    又因为cost=log2∗((level+ai)/level)cost=log2*((level+a_i)/level)cost=log2∗((level+ai​)/level),cost会带着log ...

  7. * poj 3159 Candies 最短路 dijkstra堆优化

    题意: n个人,m个信息,每行的信息是3个数字,A,B,C,表示B比A多出来的糖果不超过C个,问你,n号人最多比1号人多几个糖果 Input: 输入包含单个测试用例.测试用例以两个整数n和m开头,分别 ...

  8. HDU ACM 3986 Harry Potter and the Final Battle(邻接表实现最短路dijkstra堆优化记录路径 + 枚举最短路上每条边)...

    http://acm.hdu.edu.cn/showproblem.php?pid=3986 题意: 从起点1 到 终点n,删除图中任意一条边求最短路的最坏情况. n  --表示有n个点 m --边数 ...

  9. dijkstra算法及其堆优化

    dijkstra算法及其堆优化 (个人笔记写给自己看的) 数据结构:链式前向星,优先队列 dijkstra算法: vis数组初始化为0,dis数组初始化为inf(很大的值如:0x7fffffff),设 ...

最新文章

  1. java简单通讯录的实现02person类_用java实现简单的小游戏(你一定玩过)
  2. C#调用C++dll
  3. 循环链表的插入和删除
  4. PADS VX2.x安装教程
  5. 编程判断元素归类_如何使用jquery判断一个元素是否含有一个指定的类(class)...
  6. C#中如何得到Graphics对象
  7. 外贸常用术语_外贸中常用的会计术语及付款方式术语 | 会计英语
  8. bat批处理教程 24
  9. java嵌套对象,java – 从嵌套流中收集一组对象
  10. 记AELF区块链网络的一次内存持续增长问题排查
  11. php的date比较时间差,php date 时间差
  12. Android项目同步,如何通过gradle任务同步Android项目?
  13. VMware vSphere Management Assistant Guide
  14. Redhat/Ubuntu/Windows下安装Docker
  15. html5实现拖拽上传图片,JS HTML5拖拽上传图片预览
  16. 源码-PL/SQL从入门到精通-第二章-PL/SQL基本概念-Part 1
  17. 《阿里铁军》的读书笔记和读后感范文2600字
  18. 21届秋招ATL宁德新能源一面面经[数据分析工程师]
  19. 【华为OD机试真题 C++】1023 - 按身高和体重排队 | 机试题+算法思路+考点+代码解析
  20. SG3525频率和占空比参数的选取

热门文章

  1. datasnap——动态注册服务类
  2. ansible之二:模块用法
  3. 关于 Hibernate 中的“脏数据”、“脏对象”
  4. python opencv用法中文教程
  5. 感知器模型为什么不能解决异或问题
  6. RTT线程管理篇——RTT什么时候调度
  7. 2021 ACDU China Tour-上海站暨数据库大咖讲坛(第4期)成功举办!(附视频回放PPT下载)...
  8. 盘点分库分表中,你一定要避开的那些坑!
  9. Oracle 12.2新特性 | 基于权重的节点驱逐
  10. 文本检测算法新思路:基于区域重组的文本检测