单源最短路径,Dijkstra | 洛谷 P4779 【模板】单源最短路径(标准版)
题意
给定一个 n 个点,m 条有向边的带非负权图,请你计算从 s 出发,到每个点的距离。
数据保证你能从 s 出发到任意点。
分析
关于 SPFA,它死了。
Dijkstra 算法由荷兰计算机科学家 E. W. Dijkstra 于 1956 年发现,1959 年公开发表。是一种求解 非负权图 上单源最短路径的算法。优先队列优化的 Dijkstra 算法的时间复杂度为 O(mlogm)。
然后重复以下操作:
- 每次寻找一个 dis 最小的点,然后对所有出边进行 松弛(relax) 操作。即对于每个点 u,都用它将相邻的所有点 v 的 dis 值更新的过程。具体来说,更新过程为 min(disv, disu+wu,v)。
直到松弛操作扩散到所有的点,算法结束。
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
struct edge{
int to, w, nxt;
}e[N];
int n, m, u, v, w, s, head[N], dis[N];
bool vis[N];
inline void add_edge(int u, int v, int w, int id){
e[id] = {v, w, head[u]};
head[u] = id;
}
struct node{
int id, dis; // 结构体记录每个点的编号和最短路长度
bool operator < (const node &x) const{ // 重载运算符
return dis > x.dis;
}
};
inline void Dijkstra(int s){
priority_queue<node> q;
memset(dis, 0x3f, sizeof dis);
memset(vis, 0, sizeof vis);
dis[s] = 0, q.push({s, 0}); // 将起点放入队列
while(!q.empty()){ // 当队列非空(即没有遍历完所有的店)
u = q.top().id; q.pop(); // 取出队首(由于使用了优先队列,队首即为 dis 最小的点)
if(vis[u]) continue;
vis[u] = 1;
for(int i = head[u]; ~i; i = e[i].nxt){ // 遍历所有出边
v = e[i].to;
if(dis[v] > dis[u] + e[i].w){ // 松弛操作
dis[v] = dis[u] + e[i].w;
if(!vis[v]) q.push({v, dis[v]}); // 遍历到 v,则将 v 也加入队列
}
}
}
return;
}
int main(){
ios::sync_with_stdio(false);
memset(head, -1, sizeof head);
cin >> n >> m >> s;
for(int i = 1; i <= m; i++){
cin >> u >> v >> w;
add_edge(u, v, w, i);
}
Dijkstra(s);
for(int i = 1; i <= n; i++)
cout << dis[i] << ' '; // 依次输出每个点的 dis 值
return 0;
}
望穿寂夜晨曦至,雄鹰展翅图九天。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】