[luogu1119] 灾后重建
Posted neworld2002
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[luogu1119] 灾后重建相关的知识,希望对你有一定的参考价值。
Solution
虽然没做过多少Floyd的题……但是还是灵性了一波。
首先你会发现数据是有单调性的!那么我们就干脆一个一个点加进去跑Floyd就行了,那么怎么加点呢?
对于某个点key,我要把它加进去,我们可以假设它是起点,那么以i为中点,j为终点,跑一下平方的松弛操作;同上,分别假设key为终点,key为中点。
这样我们每加入一个点,它的循环次数跟跑一次完整的Floyd一样了,避免了重复计算。
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 205
#define INF 100005
int Graph[MAXN][MAXN];
int vis[MAXN];
int over[MAXN];
int N,M,Q;
inline void add(int key){
for(register int i=1;i<key;++i)
for(register int j=1;j<key;++j){
Graph[key][j] = std::min(Graph[key][j],Graph[key][i]+Graph[i][j]);
}
for(register int i=1;i<key;++i)
for(register int j=1;j<key;++j){
Graph[j][key] = std::min(Graph[j][key],Graph[j][i]+Graph[i][key]);
}
for(register int i=1;i<key;++i)
for(register int j=1;j<key;++j){
Graph[i][j] = std::min(Graph[i][j],Graph[i][key]+Graph[key][j]);
}
}
int main(){
std::memset(vis,0,sizeof(vis));
scanf("%d%d",&N,&M);
for(register int i=1;i<=N;++i){
scanf("%d",&over[i]);
}
for(register int i=1;i<=N;++i)
for(register int j=1;j<=N;++j){
Graph[i][j] = INF;
}
int u,v,w;
for(register int i=1;i<=M;++i){
scanf("%d%d%d",&u,&v,&w);
Graph[u+1][v+1] = w;
Graph[v+1][u+1] = w;
}
int point = 0;
scanf("%d",&Q);
int t = 0;
for(register int i=1;i<=Q;++i){
scanf("%d%d%d",&u,&v,&t);
u++;v++;
for(;point<N&&over[point+1]<=t;){
add(++point);
vis[point] = 1;
}
if(vis[u]==0||vis[v]==0||Graph[u][v]==INF)puts("-1");
else printf("%d
",Graph[u][v]);
}
return 0;
}
以上是关于[luogu1119] 灾后重建的主要内容,如果未能解决你的问题,请参考以下文章