洛谷P1119 灾后重建 题解 Floyd算法


题目链接:https://www.luogu.com.cn/problem/P1119

解题思路:

floyd变种题。主要要了解floyd算法的本质就是dp,状态 \(f_{i,j}\) 其实是状态 \(f_{i,j,k}\) 的状态压缩,表示 \(i\)\(j\) 仅由前 \(k\) 个点(或者可以想象成仅由一个序列的点,而序列的最后一个点是 \(k\))的最短路径长度。据此可以根据时间来更新 \(k\) 即状态 \(f_{i,j}\)

示例程序:

#include 
using namespace std;
const int maxn = 202;
int n, m, q, t[maxn], f[maxn][maxn], p;
bool ok[maxn];

int main() {
    ios::sync_with_stdio(0);
    cin >> n >> m;
    for (int i = 0; i < n; i ++) cin >> t[i];
    memset(f, 0x3f, sizeof(f));
    for (int i = 0; i < n; i ++) f[i][i] = 0;
    while (m --) {
        int u, v, w;
        cin >> u >> v >> w;
        f[u][v] = f[v][u] = w;
    }
    cin >> q;
    while (q --) {
        int x, y, tt;
        cin >> x >> y >> tt;
        while (p < n && t[p] <= tt) {
            ok[p] = true;
            for (int i = 0; i < n; i ++) {
                for (int j = 0; j < n; j ++) {
                    f[i][j] = min(f[i][j], f[i][p] + f[p][j]);
                }
            }
            p ++;
        }
        if (!ok[x] || !ok[y] || f[x][y] == 0x3f3f3f3f)
            cout << -1 << endl;
        else
            cout << f[x][y] << endl;
    }
    return 0;
}