注意,数据保证了t是不下降的.
既然是多源最短路问题,当然就得在Floyd上面玩花样,这里的花样就是把最外层循环拆开,每次只循环到当然时间.
如当第一次询问,求第x天时的答案,这意味着前k1(t[k1]<=x且t[k1+1]>x)个村庄已经修复,可以做中转站了,因此最外层循环变量需要遍历节点1~k1.
此后第二次询问,求第x+m天答案,只需在原有基础上使外层变量遍历节点k1~k2 (t[k2]<=x+m且t[k2+1]>x+m).以此类推.

#include <algorithm> #include <cstdio> #include <cstring> #include <iostream> using namespace std; int n, m, t[210], dist[210][210]; int main() { memset(dist, 0x3F, sizeof(dist)); scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) scanf("%d", t + i), dist[i][i] = 0; while (m--) { int x, y, w; scanf("%d%d%d", &x, &y, &w); dist[x + 1][y + 1] = dist[y + 1][x + 1] = w; } int q, k = 1; scanf("%d", &q); while (q--) { int x, y, nt; scanf("%d%d%d", &x, &y, &nt); x++, y++; if (t[x] > nt || t[y] > nt) { puts("-1"); continue; } for (; t[k] <= nt && k <= n; k++) for (int i = 1; i <= n; i++) if (i != k) for (int j = 1; j <= n; j++) if (i != j && j != k) dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]); printf("%d ", dist[x][y] == 0x3F3F3F3F ? -1 : dist[x][y]); } return 0; }
你可以把这种做法看作Floyd作为一种动态规划算法的无后效性的体现.