【题解】P1119 灾后重建

题目链接(洛谷)

题目大意

\(n\)个村庄,编号从\(0\)~\(n−1\)。给出\(m\)条双向公路连接这些村庄。

发生了一次地震,对所有村庄造成了一些损毁,但对公路没有影响。

现在要重建村庄,给出第\(i\)个村庄重建完成的时间\(t_i\)。之后又\(Q\)个询问\((x,y,t)\),对于每个询问。你要回答在第\(t\)天,从村庄\(x\)到村庄\(y\)的最短路长度为多少。如果无法找到路径或者\(x,y\)没有重建完成,输出\(−1\)

\(N\le 200,M\le \frac{N\times (N-1)}{2}, Q\le 50000\)

分析

所有的边已经给出,按照时间顺序更新每一个可用的点,求对于目前建设的村庄来说任意两点之间的最短路。

正是Floyd算法的使用前\(k\)个点更新最短路的思路。

实现

\((100pts,409ms,764.00kb)\)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include<bits/stdc++.h>

using namespace std;
const int N = 205, M = 400005;
int n, m, q;
int t[N], f[N][N], x, y, z;

void update(int k) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (f[i][j] > f[i][k] + f[j][k]) {
f[i][j] = f[j][i] = f[i][k] + f[j][k];
}
}
}
}

int main() {
cin >> n >> m;
for (int i = 0; i < n; i++) {
cin >> t[i];
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
f[i][j] = 0x3f3f3f3f;
}
}
for (int i = 0; i < n; i++) {
f[i][i] = 0;
}
for (int i = 0; i < m; i++) {
cin >> x >> y >> z;
f[x][y] = z;
f[y][x] = z;
}
cin >> q;
int cur = 0;
while (q--) {
cin >> x >> y >> z;
while (t[cur] <= z && cur < n) {
update(cur);
cur++;
}
if (t[x] > z || t[y] > z) cout << -1 << endl;
else {
if (f[x][y] == 0x3f3f3f3f) cout << -1 << endl;
else cout << f[x][y] << endl;
}

}
return 0;
}