本文已参与「新人创作礼」活动,一起开启掘金创作之路。
1️⃣题目描述
题目链接:
www.luogu.com.cn/problem/P11…
这道题良心的是重建的时间是从小到大排序的,而且询问的重建时间也是从小到大排序的,所以我们可以正向的进行操作,不需要进行排序操作。
2️⃣简单思路
本题主要是Floyd算法本质的一个理解和练习。
Floyd算法中的k表示的是中间节点,以此为中间节点可以更新两点之间的最短距离。
:代表的是i到j的最短距离
每当进行一个询问时,如果有村庄在此询问的时间点之前重建完成,就要以此村庄为中转节点,对所有点的最短距离进行更新。
更新的代码:
while(a[k] <= t && k < n)
{
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
{
if(f[i][k] + f[k][j] < f[i][j])
f[j][i] = f[i][j] = f[i][k] + f[k][j];
}
k ++;
}
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m;
cin >> n >> m;
vector<int> a(n);
for(int i = 0; i < n; i++) cin >> a[i];
vector f(n, vector(n, 1e9));
for(int i = 0; i < n; i++) f[i][i] = 0;
for(int i = 1; i <= m; i++)
{
int a, b, c;
cin >> a >> b >> c;
f[a][b] = f[b][a] = c;
}
int q;
int k = 0;
cin >> q;
while(q--)
{
int x, y, t;
cin >> x >> y >> t;
while(a[k] <= t && k < n)
{
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
{
if(f[i][k] + f[k][j] < f[i][j])
f[j][i] = f[i][j] = f[i][k] + f[k][j];
}
k ++;
}
if(a[x] > t || a[y] > t) cout << -1 << "\n";
else
{
if(f[x][y] == 1e9) cout << -1 << "\n";
else cout << f[x][y] << "\n";
}
}
return 0;
}