zoukankan      html  css  js  c++  java
  • [LuoguP1119]灾后重建

    感觉线代能上九十,开心

    刷点水题

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

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

    $n$个点 $q$次询问 $nleq200,qleq50000$

    就是改改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;
    }
  • 相关阅读:
    netty源码深度分析
    《深入探索Netty原理及源码分析》文集小结
    Netty 那些事儿 ——— 心跳机制
    CSS实现单行、多行文本溢出显示省略号(…)
    测试
    PHP 二维数组根据某个字段排序
    PHP生成图片验证码、点击切换实例
    正确设置网站title、keywords、description(转载)
    nginx上支持.htaccess伪静态的配置实例
    百度编辑器Ueditor增加字体的修改方法
  • 原文地址:https://www.cnblogs.com/ruoruoruo/p/12075133.html
Copyright © 2011-2022 走看看