知识点
dijkstra算法
介绍 :dijkstra算法用于求解有权图求最短路的问题
具体过程
1.将起始点的dis置为0.
2.选择当前未标记的顶点中dis值最小的一个。
3.对该顶点的所有连边依次进行松弛操作。
4.对该点进行标记。
5.重复第(2)步至第(4)步,直到不存在一条边从已标记顶点通往未标记点的连边
还有一点没说
搞清楚邻接表 和邻接矩阵适用于什么情况
如果不懂连边,松弛操作等名词含义欢迎拜读我的博客点我
解释:dis数组是用于记录到目前为止起点到各顶点的最短路长度
关于dis数组的细节初始化,在初始化的时候先将整个数组设置为inf,inf:表示无穷大,一般开成1e18-1或者1e9-1
题外话
其实这个算法和BFS求无权图最短路的思路差不多,基础不好的就像我一样 有点搞不懂这个dijkstra函数的形参也就是graph数组他其实存的就是比如\(u \to v\) 代价为w,那么就是graph[u].push_back({w,v}),就是存u点到v点的边权(代价),在主函数初始化的时候你可以注意到
当然我这个代码用堆优化了,也就是优先队列,也要搞懂优先队列的作用,总之你一定要知道你现在要干嘛,等下要干嘛,一定要有思路
#include <bits/stdc++.h>
using namespace std ;
#define int long long
vector<int>Dijkstra(int start,int n,vector<vector<pair<int,int> > >& graph)
{
const int INF = INT_MAX ;
vector<int>dis(n+1,INF) ;
dis[start] = 0 ;
//存{距离,节点}
priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int> > >q;
q.push({0,start});
while(!q.empty())
{
int d = q.top().first ;
int u = q.top().second ;
q.pop() ;
if(d > dis[u]) continue ;/*
在堆优化的 Dijkstra 中,我们无法直接更新队列内部某个节点的值。所以,当发现一条更短的路径时,我们并不是"修改"队列里的旧距离,而是直接塞进去一个新的、更短的距离。
这就导致:同一个节点在队列里可能同时存在多份数据。*/
//简单来说,它的核心作用是:跳过那些已经被发现"不是最短"的路径信息
for(auto & edge : graph[u])
{
int v = edge.first ; //目标节点
int w = edge.second ; //边权
if(dis[u] + w < dis[v])
{
dis[v] = dis[u] + w ;
q.push({dis[v],v}) ;
}
}
}
return dis ;
}
signed main()
{
ios::sync_with_stdio(false),cin.tie(nullptr) ;
int n,m,s;
cin >> n >> m >> s;
// 邻接表:graph[u]存储从u出发的所有边 {v, w}
vector<vector<pair<int, int>>> graph(n + 1); // 1-indexed
for(int i = 0;i < m;i++)
{
int u,v,w;
cin >> u >> v >> w ;
graph[u].push_back({v, w});
}
vector<int> dist = Dijkstra(s, n, graph);
for (int i = 1; i <= n; i++) {
if (dist[i] == INT_MAX) {
cout << 2147483647 << " "; // 不能到达
} else {
cout << dist[i] << " ";
}
}
cout << endl;
return 0 ;
}