最短路径专题3 最短距离-多边权


最短路径专题3 最短距离-多边权

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

题目:

样例:

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

思路:

根据题目意思,其实还是Dijkstra 的题目,不同的是,多了一个最少花费边权的这个点,多添加一个spend数组,结合dist数组即可,同样用堆优化方式更方便些。

代码详解如下:

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
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <unordered_map>
#define endl '\n'
#define int long long
#define YES puts("YES")
#define NO puts("NO")
#define umap unordered_map
#define INF 0x3f3f3f3f3f3f3f3f3f3f
#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;

int n,k,start,last;

int dist[N]; // 最短距离数组
int spend[N]; // 最少花费边权数组
bool st[N]; // 标记是否走动过

// 定义存储 点,距离,边权 结构体
struct Edge
{
int b; // 关系点
int dis; // 距离
int m; // 边权花费

// 构造函数
inline Edge(int _b,int _dis,int _m)
{
b = _b;
dis = _dis;
m = _m;
}

// 重载比较符号,方便堆排序
inline bool operator<(const Edge&w)const
{
// 优先选择 最短距离,其次距离相等的时候,选择最少边权的花费
if(dis != w.dis) return dis > w.dis;
else return m > w.m;
}
};

// 建立链表,e 存储的是关系点,w 存储的是距离,m 存储的是边权
int h[N],w[N],m[N],ne[N],e[N],idx;
inline void Add(int a,int b,int c,int d)
{
e[idx] = b,w[idx] = c,m[idx] = d,ne[idx] = h[a],h[a] = idx++;
}

inline void Dijkstra()
{
// 初始化最短距离数组和最少花费边权数组
memset(dist,INF,sizeof dist);
memset(spend,INF,sizeof spend);
dist[start] = 0;
spend[start] = 0;

priority_queue<Edge>q;

// 存储起点
q.push(Edge(start,0,0));

while(q.size())
{
// 获取当前存储的边权距离关系
Edge now = q.top();
q.pop();

int b = now.b; // 获取相应关系点
int dis = now.dis; // 获取相应关系距离
int spe = now.m; // 获取相应关系花费边权

// 如果当前的 b 点走动过,进入下一个关系点的判断
if(st[b]) continue;

st[b] = true; // 标记当前点

// 遍历连接的链表关系
for(int i = h[b];i != -1;i = ne[i])
{
int j = e[i]; // 获取 与 b 点连接的 相应的关系点

// 更新关系点的最短距离
if(dist[j] > dis + w[i])
{
dist[j] = dis + w[i];

// 由于一定会更新最短距离,所以花费也一定会更新
spend[j] = spe + m[i];
}else // 否则如果,最短距离相同,我们选择更新最少花费边权的
if(dist[j] == dis + w[i] && spend[j] > spe + m[i]) spend[j] = spe + m[i];

// 存储该关系点,进行下一次走动
q.push(Edge(j,dist[j],spend[j]));
}
}
}

inline void solve()
{
cin >> n >> k >> start >> last;
while(k--)
{
int a,b,c,d;
cin >> a >> b >> c >> d;

// 由于是无向图,所以添加两个点互相的链表
Add(a,b,c,d);
Add(b,a,c,d);
}

Dijkstra();

// 输出答案
cout << dist[last] << ' ' << spend[last] << endl;
}
signed main()
{
// 初始化链表
memset(h,-1,sizeof h);
// freopen("a.txt", "r", stdin);
___G;
int _t = 1;
// cin >> _t;
while (_t--)
{
solve();
}

return 0;
}

最后提交:


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

微信二维码

wechat pay

支付宝二维码

ali pay

最短路径专题3 最短距离-多边权
http://blog.angindem.cn/2023/10/03/Angindem-CSDN博客/082_82/
作者
Angindem
发布于
2023年10月3日
许可协议