P1119 灾后重建

注意,数据保证了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;
}
P1119

你可以把这种做法看作Floyd作为一种动态规划算法的无后效性的体现.

原文地址:https://www.cnblogs.com/Gaomez/p/14511756.html