小白进阶之路-Luogu P1119

看完题目思索一会,发觉自己想了个假算法(但居然只能过样例,一定是自定义的三元祖很憨批) 就是每次把查询按时间排序,然后逐渐加入可以加入的边,跑Dijkstra,很明显,WA了8个,TLE了两个,被自己蠢怕了。
看了题解就会发现,Floyed已经攻占了题解区。
其实也不难理解,就是在不断更新可以使用维护的边去更新最短路的值(脑子短路的我没有看到关于时间t的输入都是不下降的。。。,还一直在想要不要排序) Folyed本身就是n遍利用第i个点更新其他路径,这个题就可以用更新的点,去维护最短路。
题目链接:Here
int t[202],n,m;
int dp[202][202];
int cnt = 0;
inline void update(int k) { // 利用当前加进来的点去维护最短路
for(int i = 0;i < n;++i) {
for(int j = 0;j < n;++j) {
if(dp[i][j] > dp[i][k] + dp[k][j]) {
dp[i][j] = dp[j][i] = dp[i][k] + dp[k][j];
}
}
}
}
void solve() {
int st,ed,tt;
scanf("%d%d%d",&st,&ed,&tt);
while(t[cnt] <= tt && cnt < n) {
update(cnt);
++cnt;
}
if(t[st] > tt || t[ed] > tt) {
printf("-1\n");return ;
}else {
if(dp[st][ed] == inf) printf("-1\n");
else printf("%d\n",dp[st][ed]);
}
}
int main() {
for(int i = 0;i <= 200;++i){
for(int j = 0;j <= 200;++j) {
if(i == j) dp[i][j] = 0;
else dp[i][j] = inf; // inf == 0x3f3f3f3f
}
}
scanf("%d%d", &n,&m);
for(int i = 0;i < n;++i) scanf("%d", &t[i]);
for(int i = 0;i < m;++i){
int u,v,w;scanf("%d%d%d",&u,&v,&w);
dp[u][v] = w; // 好吧,我刚开始也没看到是双向边,我个憨憨
dp[v][u] = w;
}
int k;scanf("%d",&k);
while(k--) solve();
return 0;
}

浙公网安备 33010602011771号