dijkstra算法及其优化

dijkstra算法是经典的贪心算法。基本的想法是,有两个集合S和E,开始S集合中只有一个起点,E集合中有剩下的其他点。遍历E集合中的所有点,找出与起点距离最近的一个点,将其加入集合S,并用该点去更新起点到其他点的最短路径。

由动图结合上面的思路,我们可以看出,算法的基本框架是:

1 1.初始化
2 for i(0 -> n - 1)
3 {
4     2.找出距离起点最近的点
5     3.标记该点加入集合S
6     4.用新加入集合S的点去更新起点到其他点的最短距离
7 }

1.其中初始化包括了距离数组dis,将dis数组初始化为无穷大,将第一个点的距离置为0。

2.循环n - 1次是因为n个点只需添加n - 1个点到集合S,每做一次循环添加一个点,所以是循环n - 1次。

3.标记新点加入集合用一个st数组记录即可。

4.dis[i]表示的是起点s到i的点距离,所以用新点a去更新起点s到其他点(例如b点)的最短路径就是比较dis[a] + (a到b的距离)和 dis[b]的大小,将dis[b]置成两者中的最小值。

5.可以注意的是在伪代码中的2步:找出距离起点最近的点,要遍历剩下的所有点,所以时间复杂度是O(n),但是我们联想到,在一堆数字中找出一个最小值,可以用堆进行优化,时间复杂度是可以由O(n)降到O(logn)的。所以这就是dijkstra的堆优化,可以将时间复杂度为O(mn)降为O(mlogn)。但是在稀疏图中使用较好。稠密图依旧是朴素的dijkstra算法效果更好。

完整代码:

朴素版本:

时间复杂度O(mn)

 1 #include <cstring>
 2 #include <iostream>
 3 #include <algorithm>
 4
 5 using namespace std;
 6
 7 const int N = 510;
 8
 9 int n, m;
10 int g[N][N];
11 int dis[N];
12 bool st[N];
13
14 int dijkstra()
15 {
16     memset(dis, 0x3f, sizeof dis);//初始化
17     dis[1] = 0;
18
19     for (int i = 0; i < n - 1; i ++ )
20     {
21         int t = -1;
22         for (int j = 1; j <= n; j ++ )//找出距离起点最近的点
23             if (!st[j] && (t == -1 || dis[t] > dis[j]))
24                 t = j;
25         st[t] = true;//标记加入集合S
26
27         for (int j = 1; j <= n; j ++ )//用该点去更新其他点
28             dis[j] = min(dis[j], dis[t] + g[t][j]);
29
30     }
31
32     if (dis[n] == 0x3f3f3f3f) return -1;
33     return dis[n];
34 }
35
36 int main()
37 {
38     cin >> n >> m;
39
40     memset(g, 0x3f, sizeof g);
41     while (m -- )
42     {
43         int a, b, c;
44         cin >> a >> b >> c;
45
46         g[a][b] = min(g[a][b], c);
47     }
48
49     cout << dijkstra() << endl;
50
51     return 0;
52 }
53
54     

堆优化版本:

时间复杂度O(mlogn)

 1 #include <cstring>
 2 #include <iostream>
 3 #include <algorithm>
 4 #include <queue>
 5
 6 using namespace std;
 7
 8 typedef pair<int, int> PII;
 9
10 const int N = 1e5 + 10;
11
12 int n, m;
13 int h[N], w[N], e[N], ne[N], idx;
14 int dist[N];
15 bool st[N];
16
17 void add(int a, int b, int c)
18 {
19     e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
20 }
21
22 int dijkstra()
23 {
24     memset(dist, 0x3f, sizeof dist);//初始化
25     dist[1] = 0;
26     priority_queue<PII, vector<PII>, greater<PII>> heap;//小根堆
27     heap.push({0, 1});//第一个参数是距离,第二个参数是编号
28
29     while (heap.size())
30     {
31         PII t = heap.top();
32         heap.pop();
33
34         int ver = t.second, distance = t.first;
35
36         if (st[ver]) continue;//如果已经加入集合过就跳过
37         st[ver] = true;
38
39         for (int i = h[ver]; i != -1; i = ne[i])
40         {
41             int j = e[i];
42             if (dist[j] > distance + w[i])
43             {
44                 dist[j] = distance + w[i];
45                 heap.push({dist[j], j});
46             }
47         }
48     }
49
50     if (dist[n] == 0x3f3f3f3f) return -1;
51     return dist[n];
52 }
53
54 int main()
55 {
56     cin >> n >> m;
57
58     memset(h, -1, sizeof h);
59     while (m -- )
60     {
61         int a, b, c;
62         cin >> a >> b >> c;
63         add(a, b, c);
64     }
65
66     cout << dijkstra() << endl;
67
68     return 0;
69 }

原文地址:https://www.cnblogs.com/1-0001/p/12229393.html

时间: 2024-10-16 23:28:46

dijkstra算法及其优化的相关文章

POJ 3268 Silver Cow Party 最短路—dijkstra算法的优化。

POJ 3268 Silver Cow Party Description One cow from each of N farms (1 ≤ N ≤ 1000) conveniently numbered 1..N is going to attend the big cow party to be held at farm #X (1 ≤ X ≤ N). A total of M (1 ≤ M ≤ 100,000) unidirectional (one-way roads connects

POJ 1511 Invitation Cards 【最短路,spfa算法,Dijkstra算法堆优化】

Invitation Cards Time Limit: 8000MS   Memory Limit: 262144K Total Submissions: 25219   Accepted: 8346 Description In the age of television, not many people attend theater performances. Antique Comedians of Malidinesia are aware of this fact. They wan

Dijkstra算法堆优化(vector建图)

#include<iostream> #include<algorithm> #include<string.h> #include<stdio.h> #include<queue> #include <vector> #include <map> int s,t; int n,m; using namespace std; const int INF=99999999; struct Node{ int to; int

【裸单源最短路:Dijkstra算法两种版本】hdu 1874 畅通工程续

Source : hdu 1874 畅通工程续 http://acm.hdu.edu.cn/showproblem.php?pid=1874 Problem Description 某省自从实行了很多年的畅通工程计划后,终于修建了很多路.不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离要短很多.这让行人很困扰. 现在,已知起点和终点,请你计算出要从起点到终点,最短需要行走多少距离. Input 本题目包含多组数据,请处理到文件结束.

最短路的几种算法及其优化(模板)

一.Dijkstra 算法 dijkstra算法适用于边权为正的情况,求单源最短路,适用于有向图和无向图 模板伪代码: 清除所有点的标号 设d[0]=0,其余d[i]=INF: 循环n次{ 在所有未标记的节点中,寻找d[i]最小的点x 给x做标记 对于从x出发的所有边(x,y)更新d[y]=min(d[y],d[x]+w[x,y]); } memset(v,0,sizeof(v)); for(int i=0;i<n;++i) d[i]=(i==0?0:INF); for(int i=0;i<n

求解最短路的四个算法及其优化

目录 求解最短路的四个算法及其优化 1.Dijkstra算法 <1.朴素Dijkstra算法: <2:堆优化的Dijkstra算法 2.Floyd算法 3.Bellman-Ford算法 4.SPFA算法 求解最短路的四个算法及其优化 1.Dijkstra算法 Dijkstra很好的运用了贪心算法,其思想是一直找离已加入顶点集合的最短边,更新邻点,下面是实现代码: <1.朴素Dijkstra算法: [题意]:给定一个n个点m条边的有向图,图中可能存在重边和自环,所有边权均为正值.请你求出1

配对堆优化Dijkstra算法小记

关于配对堆的一些小姿势: 1.配对堆是一颗多叉树. 2.包含优先队列的所有功能,可用于优化Dijkstra算法. 3.属于可并堆,因此对于集合合并维护最值的问题很实用. 4.速度快于一般的堆结构(左偏树,斜堆,随机堆--),具体时间复杂度: 合并(Merge):$O(1)$: 插入(Insert/Push):$O(1)$: 修改值(Change):$O(1) \sim O(\log n)$: 取出维护的最值(Top):$O(1)$: 弹出堆顶元素(Pop):$O(\log n)$: 我们依然拿洛

P103 Dijkstra算法 单源最短路问题优化算法

///标准的dijkstra算法 void dijkstra() { while(true) { int vert=-1; dis[-1]=INF; for(int i=0;i<num_v;i++) { if( (!used[i]) && ( vert==-1||dis[i]<dis[vert] ) ) {vert=i;} } if(vert==-1) break;///这里要提前break;好像是这样... used[vert]=1; for(int i=0;i<num

互联网IP合全局路由优化的原则-Dijkstra算法证明

周末继续写东西的一半填补了,为了达到完美的一天.我们知道一个事实,IP地址太多.统一管理是不可能的了,无论从控制平面从数据/管理层表示,飞机是如此. 所以.IP协议被设计为可伸缩.供IP路由术语,跳路由进行计算.当然,支持"源路由",源路由就是说数据在出发前就已经把路线规划好了,逐跳路由是IP路由的标准形式.也就是说.IP数据包是在路上即时规划路线的.       我比較喜欢IP路由是由于这也是我旅行的方式,我喜欢旅行,可是我不喜欢事先订酒店.事先规划路线.导航等,我的方式是在路上看路