灾后重建「解题报告」

Posted jhtblog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了灾后重建「解题报告」相关的知识,希望对你有一定的参考价值。

P1119 灾后重建

Luogu P1119

题意

有n个村庄m条路,每个村庄都被地震摧毁,在某一时刻 \(t_i\)被修好。对于某条路,只有当它连接的两个村庄都被修好后才能通过。有q个询问,询问在某一时刻两村庄间的最短路。

第一行包含两个正整数 \(n,m\)

第二行包含 \(n\) 个非负整数 \(t_0, t_1,…, t_N-1\),表示每个村庄重建完成的时间,数据保证了 \(t_0 ≤ t_1 ≤ … ≤ t_N-1\)

接下来 \(m\) 行,每行3个非负整数 \(i,j,w\)\(w≤10000\) 表示了有一条连接村庄 \(i,j\) 的道路,长度为 \(w\),保证 \(i\neq j\),对于任意一对村庄只会存在一条道路。

接下来一个正整数 \(q\) ,表示 \(q\) 个询问。

接下来 \(q\) 行,每行3个非负整数 \(x,y,t\) ,询问在第 \(t\) 天,从村庄 \(x\) 到村庄 \(y\) 的最短路径长度为多少,数据保证了 \(t\) 是不下降的。

解析

看到最短路就先无脑写了个Dij。T掉后发现正解竟然是Floyd!

因为询问中的 \(t\) 是不降的,所以村庄是被顺序修好的,如果 \(t_i\leq t\) ,那么1~ i 号村庄已经完成重建。

所以在Floyd中,当村庄 \(k\) 完成重建后,用 \(k\) 进行松弛操作。

显然村庄只会被重修一次,所以复杂度是 \(O(n^3)\) 的。

而Dij的 \(O(q\cdot n\log_2(n) )\) 显然是不能接受的。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;

long long n,m,q;
long long t[500];

long long k=1;

long long mape[500][500];

int main() 
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;++i) 
        for(int j=1;j<=n;++j) 
            mape[i][j]=0x7fffffff;
    for(int i=1;i<=n;++i) scanf("%lld",&t[i]);
    for(int i=1;i<=m;++i) 
        long long x,y,z;
        scanf("%lld%lld%lld",&x,&y,&z);
        mape[x+1][y+1]=z;
        mape[y+1][x+1]=z;
    
    scanf("%lld",&q);
    while(q--) 
        long long x,y,z;
        scanf("%lld%lld%lld",&x,&y,&z);
        ++x;++y;
        for(;t[k]<=z&&k<=n;++k)
            for(int i=1;i<=n;++i)
                for(int j=1;j<=n;++j) 
                    mape[i][j]=min(mape[i][j],mape[i][k]+mape[k][j]);
                    mape[j][i]=min(mape[j][i],mape[j][k]+mape[k][i]);
                
        if(mape[x][y]<0x7fffffff&&t[x]<=z&&t[y]<=z) printf("%d\n",mape[x][y]);
        else printf("-1\n");
    

以上是关于灾后重建「解题报告」的主要内容,如果未能解决你的问题,请参考以下文章

解题报告力扣 第 277 场周赛

解题报告力扣 第 285 场周赛

解题报告力扣 第 268 场周赛

解题报告力扣 第 271 场周赛

解题报告力扣 第 263 场周赛

解题报告力扣 第 269 场周赛

(c)2006-2024 SYSTEM All Rights Reserved IT常识