/*
dirkstra最短路径模板 洛谷P4779
最短路径之Dijkstra 迪杰斯特拉
解决带权重的有向图,其权值只能是正值,不能解决负值问题。 无向图也可以,存两边就好了 nums[u].push_back() nums[v].push_back()
基本思想:利用广度优先搜索的方法,更新起点到各个顶点的最短距离。
是一种经典的求单源最短路径的一种方法。
具体做法:定义一个数组T 保留源点到各顶点的最短距离,和一个数组表示以及遍历出最短路径的数组S
*/
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn = 2e5+10;
const int INF=1e18;
struct node{
int v,w;
bool operator <(const node &a)const{
return a.w<w; // 升序 与 sort 相同 a.w<b.w // w本身就理解为b.w就好
}
};
vector<node> nums[maxn]; // 邻接表 # 其他方式:邻接矩阵 链式前向星
priority_queue<node> q; // 优先队列
int dis[maxn]; // 目的点到当前点的距离
void Dijkstra(int s){
fill(dis,dis+maxn,INF);
dis[s]=0; // 标记 出发点的距离为0
q.push({s,0}); // 将出发点的信息存入优先队列
while(!q.empty()){ // 判断优先队列是否为空
node a = q.top(); // 取出当下距离最小的点(优先队列-升序排列 1 2 3 4 所有top=1)
q.pop(); // 从队列中删除 取出的点
int u = a.v;
if(a.w!=dis[u]) continue; // 如果取出点的距离和它对应dis中的值不同了,说明dis值以及有更好的路线了,因此跳过执行该点
for(int i=0;i<nums[u].size();i++){ // 遍历与这个点相连的所有线路
int v = nums[u][i].v;
if(dis[u]+nums[u][i].w<dis[v]){ // 如果这个点 加上本身 的距离 小于 当前到达目的地所需的距离
dis[v]=nums[u][i].w+dis[u]; // 更新到达目的地的距离
q.push({v,dis[v]}); // 将这个点存入队列
}
}
}
} // 思考:如果要记录最短的路径呢 该怎么记录呢?
void Solve(){
int n,m,s;
scanf("%lld %lld %lld",&n,&m,&s);
int u,v,w;
while(m--){
scanf("%lld %lld %lld",&u,&v,&w);
nums[u].push_back({v,w});
}
Dijkstra(s);
for(int i=1;i<=n;i++)
printf("%lld ",dis[i]);
}
signed main(){
Solve();
}
dirkstra最短路径模板 洛谷P4779
于 2023-07-20 11:42:39 首次发布