这道题一眼看上去...Floyd..?
每个村庄修复时间、询问都是不下降的...似乎连排序都省略了x
既然这样,那每次询问时,更新这个询问之前的村庄来求目前的最短路径就可以了
注意事项:对于这个循环
for(; t[k] <= z && k < n; k++) {
f[k] = true;
floyd(k);
}
1.k不能定义为for内部的局部变量(因为之前的村庄已经遍历过了不需要再走一遍)
(否则时间复杂度会从O(n^3)变为O(q*n^3))
2.注意判断边界(k < n),否则当询问时间超出最后一个村庄的修复时间时就会陷入循环x
代码如下
#include<cstdio> #include<iostream> using namespace std; const int INF = 100005; const int maxn = 205; int n,m,q,x,y,z,k; int t[maxn],dis[maxn][maxn],ans[maxn][maxn]; bool f[maxn]; void floyd(int k) { for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) { dis[i][j] = min(dis[i][j],dis[i][k]+dis[k][j]); ans[i][j] = min(ans[i][j],dis[i][j]); } } int main() { scanf("%d%d",&n,&m); for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) { dis[i][j] = INF; ans[i][j] = INF; if(i == j)dis[i][j] = 0; } for(int i = 0; i < n; i++) scanf("%d",&t[i]); for(int i = 0; i < m; i++) { scanf("%d%d%d",&x,&y,&z); dis[x][y] = z; dis[y][x] = z; } scanf("%d",&q); for(int i = 0; i < q; i++) { scanf("%d%d%d",&x,&y,&z); for(; t[k] <= z && k < n; k++) { f[k] = true; floyd(k); } if(ans[x][y] == INF || !f[x] || !f[y])printf("-1\n"); else printf("%d\n",ans[x][y]); } return 0; }