题意
n个村庄的编号从0 - n-1,现在又m条马路连接,但是每条马路有一个连通的时间,你需要回答q个问题,问你a到b在第t天的时候的最短路径是多少?
思路
用来做Floyd练手的。
首先要知道Floyd算法的本质,它实质是一个dp,可以这么说,一个点到另外一个点,它们之间有n个中转站,你现在要找一个使这两个点的距离最近的中转站,就是这么个意思。
回到这个题,这个题可以用Dijkstra或者SPFA。现在想一想Floyd,题中告诉了你每个村庄完成重建的时间,并且给你的是递增的顺序,这样我们就省了给时间排序的步骤。这个时候我们一次遍历每个节点,以这个节点为中转站,来进行更新,这个时候中转站的重建时间要比给定的时间要小,然后在来求两个点之间的最短距离即可。后面再来看问的两个点的时间是否在给定的范围内,如果在我们就输出,反之则输出“-1”。
#include <bits/stdc++.h>
using namespace std;
const int N = 210, inf = 0x3f3f3f3f;
int n, m;
int t[N];
int d[N][N];
void Floyd(int x)
{
for (int i = 0; i < n; i ++)
for (int j = 0; j < n; j ++)
d[i][j] = min(d[i][j], d[i][x] + d[x][j]);
}
void solve()
{
cin >> n >> m;
for (int i = 0; i < n; i ++)
for (int j = 0; j < n; j ++)
if (i == j) d[i][j] = 0;
else d[i][j] = inf;
for (int i = 0; i < n; i ++) cin >> t[i];
while (m --)
{
int a, b, c; cin >> a >> b >> c;
d[a][b] = d[b][a] = c;
}
int cur = 0;
int q; cin >> q;
while (q --)
{
int a, b, c; cin >> a >> b >> c;
while (t[cur] <= c && cur < n) { Floyd(cur); cur ++; }
if (t[a] > c || t[b] > c || d[a][b] == inf) cout << "-1" << endl;
else cout << d[a][b] << endl;
}
}
signed main()
{
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
solve();
return 0;
}