最短路径专题5 最短路径


最短路径专题5 最短路径

原创 于 2023-10-04 22:20:19 发布 · 粉丝可见 · 438 阅读 · 0 · 0 · 本内容遵循CC 4.0 BY-SA版权协议 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 GEO检测 · 编辑
文章链接:https://blog.csdn.net/hacker_51/article/details/133563116

题目:

样例:

cobol<br/>4 5 0 2<br/>0 1 2<br/>0 2 5<br/>0 3 1<br/>1 2 2<br/>3 2 2<br/>
3 0->3->2

思路:

根据题目意思,求最短路,这个根据平时的 Dijkstra(堆优化) 即可,关键在于求路径的方法,求路径的方法有很多种,其中最经典的就是通过DFS递归求路径,其中我之前做的笔记 BFS求路径 便是用到了该方法。

1、 初始化记录数组为某一个特定值 ,比如初始化为  -1,方便递归求路径边界;

2、记录 当前结点是由哪上一个结点 走动的;

3、DFS递归求路径函数, 由于是当前结点记录上一个结点,所以递归由终点开始,到起点结束。

代码详解如下:

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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <unordered_map>
#define endl '\n'
#define x first
#define y second
#define mk make_pair
#define int long long
#define NO puts("NO")
#define YES puts("YES")
#define umap unordered_map
#define INF 0x3f3f3f3f3f3f3f3f
#define All(x) (x).begin(),(x).end()
#pragma GCC optimize(3,"Ofast","inline")
#define ___G std::ios::sync_with_stdio(false),cin.tie(0), cout.tie(0)
using namespace std;
const int N = 2e6 + 10;
using PII = pair<int,int>;

int n,m,start,last;

int dist[N]; // 记录最短路距离
int tree[N]; // 记录路径
bool st[N]; // 标记走动结点

vector<int>path; // 存储路径结点

// 建立链表
int h[N],e[N],w[N],ne[N],idx;
inline void Add(int a,int b,int c)
{
e[idx] = b,w[idx] = c,ne[idx] = h[a],h[a] = idx++;
}

inline void Dijkstra()
{
// 初始化记录路径数组
memset(tree,-1,sizeof tree);
// 初始化最短距离
memset(dist,INF,sizeof dist);
dist[start] = 0;

// 建立堆
priority_queue<PII,vector<PII>,greater<PII>>q;

// 存储起点和最短距离的对组
q.push(mk(0,start));

// 开始堆排序的求值
while(q.size())
{
// 获取当前结点的对组
PII now = q.top();
q.pop();

int a = now.y; // 获取当前结点
int dis = now.x;// 获取当前结点相关的最短距离
// 如果当前结点走动过,进入下一个结点的最短距离更新
if(st[a]) continue;
st[a] = true; // 标记当前结点

for(int i = h[a];i != -1;i = ne[i])
{
// 获取相关结点
int j = e[i];

// 更新最短距离
if(dist[j] > dis + w[i])
{
dist[j] = dis + w[i];
tree[j] = a; // 记录当前结点 j 由 a 走动得来的
}

// 存储当前结点 j 和相关最短距离 的对组
q.push(mk(dist[j],j));
}
}
return ;
}

void getPath(int now)
{
// 如果当前状态到达了边界起点
// 那么开始回溯递归取路径
if(now == start)
{
path.emplace_back(now);
return ;
}
// 递归上一个结点
getPath(tree[now]);

// 回溯回来,取当前结点
path.emplace_back(now);
}

inline void solve()
{
// 初始化链表
memset(h,-1,sizeof h);

cin >> n >> m >> start >> last;
while(m--)
{
int a,b,c;
cin >> a >> b >> c;

// 由于是无向图,添加相连两个结点的链表
Add(a,b,c);
Add(b,a,c);
}
// Dijkstra 求值
Dijkstra();

// 根据终点递归获取路径
getPath(last);

// 输出最短距离
cout << dist[last] << ' ';

// 输出最短路径
bool rem = false; // 控制输出格式
for(int i : path)
{
if(rem) cout << "->";
cout << i;
rem = true;
}
return ;
}

signed main()
{
// freopen("a.txt", "r", stdin);
___G;
int _t = 1;
// cin >> _t;
while (_t--)
{
solve();
}

return 0;
}

最后提交:


觉得不错的话,给点打赏吧 ୧(๑•̀⌄•́๑)૭

微信二维码

wechat pay

支付宝二维码

ali pay

最短路径专题5 最短路径
http://blog.angindem.cn/2023/10/04/Angindem-CSDN博客/084_84/
作者
Angindem
发布于
2023年10月4日
许可协议