【讲解 + 模板】Dijkstra迪杰斯特拉+堆优化
来源:互联网 发布:淘宝预约快递寄件 编辑:程序博客网 时间:2024/05/17 08:29
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相连的每个未确定最短路径的顶点j if(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 2147483647using 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 costint 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;}
阅读全文
0 0
- 【讲解 + 模板】Dijkstra迪杰斯特拉+堆优化
- Dijkstra+堆优化 模板
- [ 模板 ] 堆优化Dijkstra
- Dijkstra+堆优化模板
- 最短路~dijkstra堆优化模板
- Dijkstra算法+堆优化(模板)
- 单源最短路---dijkstra模板(二叉堆优化)
- 堆优化的dijkstra(迪杰斯特拉)
- Dijkstra+堆优化模板 (手写堆简单易懂)
- P3371 【模板】单源最短路径 SPFA优化 dijkstra堆优化
- hdu 2544 单源最短路问题 dijkstra+堆优化模板
- 最短路模板[spfa][dijkstra+堆优化][floyd]
- 洛谷 P3371 【模板】单源最短路径(Dijkstra + 堆优化)
- dijkstra堆优化 详解(洛谷模板题)
- 堆优化的Dijkstra
- DIJKSTRA堆优化
- Dijkstra + 堆优化
- 堆优化Dijkstra模版
- Hadoop安装教程_单机/伪分布式配置_Hadoop2.6.0/Ubuntu14.04
- live555搭建服务
- Python学习笔记(十)
- python基础实例6:列表复制
- mamp for mac php版本问题
- 【讲解 + 模板】Dijkstra迪杰斯特拉+堆优化
- Js操作Select大全(取值、设置选中等等)
- VSCode自定义快捷键运行插件命令(为插件设置自定义快捷键)
- Java对象与json对象之间的转换
- 137
- Linux内核抢占机制(preempt)
- 24 exdata架构探讨--优化主题系列
- mysql查询报错: ORDER BY clause is not in GROUP BY..this is incompatible with sql_mode=only_full_group_by
- Linux free命令使用及解析