第一眼看这道题感觉能很快切掉,但是后来才发现原来……
这么坑……
一开始,每一次重头开始计算并且dis和g互相赋值,浪费了很多时间,就只有30分,所以第二次就每一次记录last值域(就是上一次Floyd枚举到了那个点),再往后更新。但是只是有问题的,因为Floyd属于动态规划,必须要每次从头来找,这样才能保证更新到所有情况。
所以第三次我就就每一次记录last值,但是还是从0到last枚举,又变成0分了……
因为我每一次加入一个点,那么必须看这个点对所有的点是否有贡献,以后还可能会用到这个贡献之后的值。
改之后40分……
因为每一次会连着到n一起更新,而有的那个点是到不了的但是被赋值了(因为输出-1条件是dis[x][y]是否为-1)……需要一个vis判断是否到过。
改了之后就AC了qwq
代码如下:
#include<cstdio> #include<iostream> #include<cstring> using namespace std; #define maxn 1010 #define INF 99999999 int dis[maxn][maxn],g[maxn][maxn],n,m,q,ok[maxn],vis[maxn]; int last=0; void Floyd(int t) { for(int i=0; i<n; i++) for(int j=0; j<n; j++) { g[i][j]=min(g[i][t]+g[t][j],g[i][j]); dis[i][j]=min(dis[i][j],g[i][j]); g[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]=g[i][j]=INF; if(i==j) dis[i][j]=g[i][j]=0; } for(int i=0; i<n; i++) scanf("%d",&ok[i]); for(int i=0; i<m; i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); g[x][y]=z; g[y][x]=z; } scanf("%d",&q); while(q--) { int x,y,t; scanf("%d%d%d",&x,&y,&t); for(; t>=ok[last]&&last<n; last++) { vis[last]=1; Floyd(last); } if(dis[x][y]==INF||!vis[x]||!vis[y]) { printf("-1 "); continue; } else printf("%d ",dis[x][y]); } return 0; }