1. 程式人生 > 其它 >洛谷P1119 災後重建 題解 Floyd演算法

洛谷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 <bits/stdc++.h>
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;
}