最短路-弗洛伊德-灾后重建

题目 P1119: 灾后重建

题目背景

B 地区在地震过后,所有村庄都造成了一定的损毁,而这场地震却没对公路造成什么影响。但是在村庄重建好之前,所有与未重建完成的村庄的公路均无法通车。换句话说,只有连接着两个重建完成的村庄的公路才能通车,只能到达重建完成的村庄。

题目描述

给出 B 地区的村庄数 NNN,村庄编号从 000N−1N-1N1,和所有 MMM 条公路的长度,公路是双向的。并给出第 iii 个村庄重建完成的时间 tit_iti,你可以认为是同时开始重建并在第 tit_iti 天重建完成,并且在当天即可通车。若 tit_iti000 则说明地震未对此地区造成损坏,一开始就可以通车。之后有 QQQ 个询问 (x,y,t)(x,y,t)(x,y,t),对于每个询问你要回答在第 ttt 天,从村庄 xxx 到村庄 yyy 的最短路径长度为多少。如果无法找到从 xxx 村庄到 yyy 村庄的路径,经过若干个已重建完成的村庄,或者村庄 xxx 或村庄 yyy 在第 ttt 天仍未重建完成,则需要输出 −1-11

输入格式

第一行包含两个正整数 N,MN,MN,M,表示了村庄的数目与公路的数量。

第二行包含 NNN 个非负整数 t0,t1,⋯ ,tN−1t_0,t_1,\cdots,t_{N-1}t0,t1,,tN1,表示了每个村庄重建完成的时间,数据保证了 t0≤t1≤⋯≤tN−1t_0 \le t_1 \le \cdots \le t_{N-1}t0t1tN1

接下来 MMM 行,每行 333 个非负整数 i,j,wi,j,wi,j,wwww 不超过 100001000010000,表示了有一条连接村庄 iii 与村庄 jjj 的道路,长度为 www,保证 i≠ji\neq ji=j,且对于任意一对村庄只会存在一条道路。

接下来一行也就是 M+3M+3M+3 行包含一个正整数 QQQ,表示 QQQ 个询问。

接下来 QQQ 行,每行 333 个非负整数 x,y,tx,y,tx,y,t,询问在第 ttt 天,从村庄 xxx 到村庄 yyy 的最短路径长度为多少,数据保证了 ttt 是不下降的。

输出格式

QQQ 行,对每一个询问 (x,y,t)(x,y,t)(x,y,t) 输出对应的答案,即在第 ttt 天,从村庄 xxx 到村庄 yyy 的最短路径长度为多少。如果在第 ttt 天无法找到从 xxx 村庄到 yyy 村庄的路径,经过若干个已重建完成的村庄,或者村庄 xxx 或村庄 yyy 在第 ttt 天仍未修复完成,则输出 −1-11

样例输入输出

示例 #1

输入

4 5
1 2 3 4
0 2 1
2 3 1
3 1 2
2 1 4
0 3 5
4
2 0 2
0 1 2
0 1 3
0 1 4

输出

-1
-1
5
4

解决方案

下面是一个解决方案,它使用Floyd-Warshall算法动态更新最短路径,并处理每个查询。

#include<bits/stdc++.h>
using namespace std;
using ll = long long;

const int N = 210, inf = 1e9;

int a[N];

int n, m, w[N], d[N][N];

void update(int k){
	for(int i = 1;i <= n;i ++)
		for(int j = 1;j <= n;j ++)
			if(d[i][j] > d[i][k] + d[k][j])
				d[i][j] = d[j][i] = d[i][k] + d[k][j];
}

int main(){
	ios::sync_with_stdio(0), 
	cin.tie(0), cout.tie(0);
	cin >> n >> m;
	for(int i = 1;i <= n;i ++)cin >> w[i];
	
	for(int i = 1;i <= n;i ++)
		for(int j = 1;j <= n;j ++)d[i][j] = inf;
	for(int i = 1;i <= n;i ++)d[i][i] = 0;
	
	for(int i = 1;i <= m;i ++){
		int u, v, c;
		cin >> u >> v >> c;
		d[u + 1][v + 1] = d[v + 1][u + 1] = c;
	}
	int q;cin >> q;
	int now = 1;
	for(int i = 1;i <= q;i ++){
		int u, v, t;cin >> u >> v >> t;
		u ++, v ++;
		while(w[now] <= t && now <= n){
			update(now);
			now ++;
		}
		if(w[u] > t || w[v] > t)cout << -1 << '\n';
		else cout << (d[u][v] >= inf ? -1 : d[u][v]) << '\n';
	}
	return 0;
}

说明

该程序首先初始化村庄间的距离矩阵 d,其中 inf 表示无穷大(即不可达)。然后读取输入数据,包括村庄重建时间、公路信息等。通过 update 函数动态更新最短路径,每当有一个新的村庄重建完成时,就更新所有可能受影响的路径。最后,针对每个查询 (x, y, t),检查村庄是否在第 t 天前已经重建完成,并计算或返回最短路径长度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值