D108 最短路 Floyd 算法 P1119 灾后重建

D108 最短路 Floyd 算法 P1119 灾后重建_哔哩哔哩_bilibili

 

P1119 灾后重建 - 洛谷

无向图,如果一个点的点权 $>t$,第 $t$ 天时该点不可用。q 次询问:在第 $t$ 天,从点 x 到点 y 的最短路长度为多少。

思路

很明显是全源最短路,用 Floyd 算法,外层枚举插点时加上限制条件 a[k]<=t

​点权 “数据保证了 $t_0​≤t_1​≤⋯≤t_{N−1}$”,询问 “数据保证了 t 是不下降的”,这样插点 k 是不下降的

image

相关板子:

D04【模板】最短路 Floyd 算法 - 董晓 - 博客园

 

// 最短路+点权限制 Floyd 算法 O(n^3+q)
#include<bits/stdc++.h>
#define N 205
using namespace std;

int n,m,q,a[N],k=0;
int d[N][N];

void Floyd(int t){
  for(;a[k]<=t && k<n;k++) //枚举权值≤t的插点
  for(int i=0;i<n;i++)
  for(int j=0;j<n;j++)
  if(d[i][j]>d[i][k]+d[j][k])
    d[i][j]=d[j][i]=d[i][k]+d[j][k];
}
int main(){
  cin>>n>>m;
  for(int i=0;i<n;i++)scanf("%d",a+i);
  for(int i=0;i<n;i++)for(int j=0;j<n;j++)d[i][j]=1e9;
  for(int i=0;i<n;i++)d[i][i]=0;
  for(int i=1,u,v,w; i<=m; i++){
    scanf("%d%d%d",&u,&v,&w);
    d[u][v]=d[v][u]=w;
  }
  cin>>q;
  for(int i=1,u,v,t; i<=q; i++){
    scanf("%d%d%d",&u,&v,&t);
    Floyd(t); //最短路
    if(a[u]>t || a[v]>t) cout<<-1<<"\n"; //无插点情况
    else{
      if(d[u][v]==1e9) cout<<-1<<"\n";
      else cout<<d[u][v]<<"\n";
    }
  }
}

 

posted @ 2026-03-21 11:20  董晓  阅读(45)  评论(0)    收藏  举报