洛谷 P4779【模板】单源最短路径(标准版)
题目背景
2018 年 7 月 19 日,某位同学在 NOI Day 1 T1 归程 一题里非常熟练地使用了一个广为人知的算法求最短路。
然后呢?
100→60 ;
Ag→Cu ;
最终,他因此没能与理想的大学达成契约。
小 F 衷心祝愿大家不再重蹈覆辙。
题目描述
给定一个 N 个点, M 条有向边的带非负权图,请你计算从 S 出发,到每个点的距离。
数据保证你能从 S 出发到任意点。
输入输出格式
输入格式:
第一行为三个正整数 N, M, S。 第二行起 M 行,每行三个非负整数 ui,vi,wi ,表示从 ui 到 vi 有一条权值为 wi 的边。
输出格式:
输出一行 N 个空格分隔的非负整数,表示 S 到每个点的距离。
输入输出样例
说明
样例解释请参考 数据随机的模板题。
1 ≤ N ≤ 100000 ;
1 ≤ M ≤ 200000 ;
S = 1 ;
1 ≤ ui,vi ≤ N ;
0 ≤ wi ≤ 109,
0 ≤ ∑wi ≤ 109 。
本题数据可能会持续更新,但不会重测,望周知。
思路:spfa+优先队列优化 or dijkstra+堆优化
用P3371中的代码(再开上long long),可以过掉后两个点,但前几个点都会TLE
#include<iostream> #include<cstring> #include<cctype> #include<cstdio> #include<vector> #include<queue> #define M 100005 using namespace std; int n, m, s, a, b, c; struct Edge { int to, dis; }; vector<Edge> G[M]; inline int read() { int X = 0, z = 0; char ch = 0; while(!isdigit(ch)) z = ch == '-' ? 1 : 0, ch = getchar(); while(isdigit(ch)) X = (X<<1) + (X<<3) + (ch^48), ch = getchar(); return z ? -X : X; } long long dis[M]; bool inqueue[M]; struct Node { int x; }; bool operator < (const Node &x, const Node &y) { return dis[x.x] > dis[y.x]; } priority_queue<Node> Q; int cnt; bool hasout[M]; inline bool SPFA(int S) { memset(dis, 0x3f, sizeof dis); memset(inqueue, 0, sizeof inqueue); Q.push((Node) { S }); inqueue[S] = 1; dis[S] = 0; int u, v, cost; while(!Q.empty()) { u = Q.top().x; Q.pop(); if(!hasout[u]) cnt++; if(cnt == n) return 1; hasout[u] = 1; inqueue[u] = false; for(int i = 0; i < G[u].size(); ++i) { v = G[u][i].to; cost = G[u][i].dis; if(dis[v] > dis[u] + cost) { dis[v] = dis[u] + cost; if(!inqueue[v]) { inqueue[v] = true; Q.push((Node) { v }); } } } } return 1; } int main() { n = read(); m = read(); s = read(); for(register int i = 1; i <= m; ++i) { a = read(), b = read(), c = read(); G[a].push_back((Edge) { b, c }); } SPFA(s); for(register int i = 1; i <= n; ++i) printf("%d ", dis[i]); return 0; }