【Dijkstra】最短路算法的一种

首先,本文默认读者基本熟悉Dijkstra基本原理

  DIjkstra是单源最短路的一种算法。使用数组d[i]来储存结点i到源点s的最短路径长度,每次更新d[i]数组后,d[i]中最小的一定是一条最短路径长度。也就是说每次更新后都能找到一条最短路径,以下给出证明:

  假设d[]数组中当前最小值对应的结点为u,那么d[u]<=d[i](u != i)假设d[u]不是结点u到源点s的最短路径长度,那么一定有某种方式通过其他路径到达u,使得d[v] + w < d[u],但是由于通过源点到达其他结点的距离d[i] >= d[u] 那么不可能有其他更短的路径到达u了,故d[u]就是最短路径长度。重复以上过程n次,就能得到n个结点的最短路径长度。

  那么,具体应该怎么实现呢。

  考虑到最小值查找,我们可以考虑几种优化,比如优先队列,可以降低时间复杂度,以下是个人实现代码:

  

 1 #include<bits/stdc++.h>
 2 #define int long long
 3 using namespace std;
 4 const int INF = 1e18 + 10,maxn = 1e5 + 10;
 5 
 6 bool vis[maxn];
 7 int d[maxn];
 8 struct node{
 9     int v,w;
10     
11     //重载运算符 < 这是一种方法
12     bool operator < (const node & x) const{
13         return w > x.w;
14     }
15 };
16 int n,m;
17 vector<node> G[maxn];
18 
19 void Dijkstra(int s){
20     fill(d,d + maxn,INF);
21     //将所有点断开
22     d[s] = 0;
23     priority_queue<node> q;
24     
25     //确定最短路径
26     //当前能确定的最短路
27     q.push({s,0});
28     while(!q.empty()){
29         node t = q.top();
30         q.pop();
31         int u = t.v;
32         if(vis[u]) continue;
33         vis[u] = true;
34         //相当于结点u已经确定最短路径
35         
36         int len = G[u].size();
37         for(int i = 0; i < len; i++){
38             int v = G[u][i].v;
39             int w = G[u][i].w;
40             if(d[u] + w < d[v]){
41                 //这一步是收缩长度,找到没有确定最短路径的结点中的最小长度
42                 d[v] = d[u] + w;
43                 q.push({v,d[v]});
44             }
45         }
46     }
47     
48 }
49 signed main (){
50     ios::sync_with_stdio(false);
51     cin.tie(0),cout.tie(0);
52     
53     cin>>n>>m;
54     while(m--){
55         int u,v,w;
56         cin>>u>>v>>w;
57         G[u].push_back({v,w});
58     }
59     Dijkstra(1);
60     if(d[n] == INF){
61         cout<<-1<<'\n';
62     }else{
63         cout<<d[n]<<'\n';
64     }
65     return 0;
66 }

 

posted @ 2024-01-07 16:45  意外路过的番茄酱骑士  阅读(24)  评论(0编辑  收藏  举报