题目地址:
https://www.luogu.com.cn/problem/P4779
题目描述:
给定一个
n
n
n个点,
m
m
m条有向边的带非负权图,请你计算从
s
s
s出发,到每个点的距离。数据保证你能从
s
s
s出发到任意点。
输入格式:
第一行为三个正整数
n
,
m
,
s
n, m, s
n,m,s。 第二行起
m
m
m行,每行三个非负整数
u
i
,
v
i
u_i, v_i
ui,vi,表示从
u
i
u_i
ui到
v
i
v_i
vi有一条权值为
w
i
w_i
wi的有向边。
输出格式:
输出一行
n
n
n个空格分隔的非负整数,表示
s
s
s到每个点的距离。
数据范围:
1
≤
n
≤
1
0
5
1 \leq n \leq 10^5
1≤n≤105
1
≤
m
≤
2
×
1
0
5
1 \leq m \leq 2\times 10^5
1≤m≤2×105
s
=
1
s = 1
s=1
1
≤
u
i
,
v
i
≤
n
1 \leq u_i, v_i\leq n
1≤ui,vi≤n
0
≤
w
i
≤
1
0
9
0 \leq w_i \leq 10 ^ 9
0≤wi≤109
0
≤
∑
w
i
≤
1
0
9
0 \leq \sum w_i \leq 10 ^ 9
0≤∑wi≤109
由题目数据知图是稀疏图,要用堆优化Dijkstra算法来做。代码如下:
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
typedef pair<int, int> PII;
const int N = 1e5 + 10, M = 2e5 + 10;
int n, m, S;
int h[N], e[M], ne[M], w[M], idx;
int dist[N];
bool st[N];
void add(int a, int b, int c) {
e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++;
}
void dijkstra(int S) {
priority_queue<PII, vector<PII>, greater<PII> > heap;
memset(dist, 0x3f, sizeof dist);
dist[S] = 0;
heap.push({0, S});
while (heap.size()) {
auto t = heap.top(); heap.pop();
int v = t.second, d = t.first;
if (st[v]) continue;
st[v] = true;
for (int i = h[v]; ~i; i = ne[i]) {
int j = e[i];
if (!st[j] && dist[j] > d + w[i]) {
dist[j] = d + w[i];
heap.push({dist[j], j});
}
}
}
}
int main() {
cin >> n >> m >> S;
memset(h, -1, sizeof h);
for (int i = 0; i < m; i++) {
int a, b, c;
cin >> a >> b >> c;
add(a, b, c);
}
dijkstra(S);
for (int i = 1; i <= n; i++) cout << dist[i] << ' ';
cout << endl;
return 0;
}
时间复杂度 O ( m log n ) O(m\log n) O(mlogn),空间 O ( n ) O(n) O(n)。