[LuoguP1119]灾后重建

感觉线代能上九十,开心

刷点水题

 

题意就是不停地往图里面加点和对应的边

然后询问点对的最短路长度

$n$个点 $q$次询问 $n\leq200,q\leq50000$

就是改改floyd就行了

floyd本质上是$f[i][j][k] = min(f[i][j][k], f[i][t][k-1]+f[t][j][k-1])$

每次加点的时候自己补上就行了

#include <bits/stdc++.h>
using namespace std;
const int maxn = 200 + 10, maxm = 40000 + 10, INF = 0x3f3f3f3f;
int n, m;
int t[maxn];
int g[maxn][maxn], dis[maxn][maxn];
int main(){
    ios::sync_with_stdio(false);
    cin >> n >> m;
    for(int i = 0; i < n; i++){
        cin >> t[i];
    }
    memset(dis, 0x3f, sizeof dis);
    memset(g, 0x3f, sizeof g);
    int u, v, w;
    for(int i = 0; i < m; i++){
        cin >> u >> v >> w;
        g[u][v] = g[v][u] = w;
    }
    for(int i = 0; i < n; i++){
        g[i][i] = dis[i][i] = 0;
    }
    int last = -1, now;
    for(int i = 0; i < n; i++){
        if(!t[i]){
            for(int j = 0; j < i; j++){
                dis[i][j] = dis[j][i] = g[i][j];
            }
            last = i;
        }
        else break;
    }
    for(int k = 0; k <= last; k++){
        for(int i = 0; i <= last; i++){
            for(int j = 0; j <= last; j++){
                dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
            }
        }
    }
    int q, x, y, day;
    cin >> q;
    while(q--){
        cin >> x >> y >> day;
        if(last == -1 || day > t[last]){
            now = last + 1;
            while(now < n && t[now] <= day){
                for(int i = 0; i < now; i++){
                    dis[i][now] = dis[now][i] = g[i][now];
                }
                now++;
            }
            for(int k = last + 1; k < now; k++){
                for(int i = 0; i < now; i++){
                    for(int j = 0; j < now; j++){
                        dis[k][i] = dis[i][k] = min(dis[k][i], dis[k][j] + dis[j][i]);
                    }
                }
                for(int i = 0; i < now; i++){
                    for(int j = 0; j < now; j++){
                        dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
                    }
                }
            }
            last = now - 1;
        }
        if(dis[x][y] == INF) cout << -1 << endl;
        else cout << dis[x][y] << endl;
    }
    return 0;
}
posted @ 2019-12-20 21:27  jzyy  阅读(111)  评论(0编辑  收藏  举报