灾后重建「解题报告」
Posted jhtblog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了灾后重建「解题报告」相关的知识,希望对你有一定的参考价值。
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");
以上是关于灾后重建「解题报告」的主要内容,如果未能解决你的问题,请参考以下文章