前言
dijkstra:对于无负边的情况下可以达到O(nlogn)且很难被卡
最短路 - OI Wiki (oi-wiki.org)
P3371 【模板】单源最短路径(弱化版)
P3371 【模板】单源最短路径(弱化版) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)https://www.luogu.com.cn/problem/P3371
题目描述
如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度。
输入格式
第一行包含三个整数 n,m,s,分别表示点的个数、有向边的个数、出发点的编号。
接下来 m 行每行包含三个整数 u,v,w,表示一条 u→v 的,长度为 w 的边。
输出格式
输出一行 n 个整数,第 i 个表示 s 到第 i 个点的最短路径,若不能到达则输出 −1。
输入输出样例
输入 #1
4 6 1 1 2 2 2 3 2 2 4 1 1 3 5 3 4 3 1 4 4
输出 #1
0 2 4 3
说明/提示
【数据范围】
对于 20% 的数据:1≤n≤5,1≤m≤15;
对于 40% 的数据:1≤n≤100,1≤m≤104;
对于 70% 的数据:1≤n≤1000,1≤m≤105;
对于 100% 的数据:1≤n≤104,1≤m≤5×105,1≤u,v≤n,w≥0,∑w< ,保证数据随机。
(模板题分析见注释和链接,以及此代码可过标准版(优先队列的好处))
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e5 + 10;
struct demo{
ll x, w;
bool operator < (const demo &a) const{
if(a.w != w) return w > a.w;
return x < a.x;
}
};
vector<demo> g[N];
ll d[N], n, m, s;
void dijkstra(int st) {
memset(d, 0x3f, sizeof(ll) * (n + 1));
d[st] = 0; //起点距离为0
bitset<N> vis;
priority_queue<demo> pq;
pq.push({st, d[st]});
while(pq.size()) {
int x = pq.top().x; pq.pop();
if(vis[x]) continue;
vis[x] = 1; //标记是否走过
for(auto &[y, w] : g[x]) {
if(!vis[y] && d[y] > d[x] + w) {
d[y] = d[x] + w; //更新距离
pq.push({y, d[y]});
}
}
}
}
int main() {
ios::sync_with_stdio(false);
cin >> n >> m >> s;
int u, v, w;
for(int i = 1; i <= m; i++) {
cin >> u >> v >> w;
if(u != v) g[u].push_back({v, w});
}
dijkstra(s);
ll ans = (ll)pow(2, 31) - 1;
for(int i = 1; i <= n; i++) {
cout << (d[i] >= 4e18 ? ans : d[i]) << ' ';
}
return 0;
}