2018 宁夏  F. Moving On

给个图,有边权和点权,多组询问只能经过点权小于等于K的点的 两点之间的最短距离

先将点按照点权排序,从小到大枚举每个点作为中间的点,跑 floyd ,询问只需要找到最大的小于等于K的点权的那层图,直接输出就可以。

https://nanti.jisuanke.com/t/41290

#include <bits/stdc++.h> #define ll long long #define sc scanf #define pr printf using namespace std; #define Pair pair<int,int> Pair a[100000]; ll dp[205][205][205]; int b[205]; int n, q; void Flody() { for (int k = 1; k <= n; k++) { for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { dp[k][i][j] = min(dp[k - 1][i][j], dp[k - 1][i][a[k].first] + dp[k - 1][a[k].first][j]); } } } } int main() { int T, cas = 1; sc("%d", &T); while (T--) { pr("Case #%d:\n", cas++); sc("%d%d", &n, &q); for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) for (int k = 1; k <= n; k++) dp[i][j][k] = 1e9 + 7; for (int i = 1; i <= n; i++) { a[i].first = i; sc("%d", &a[i].second); } for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) sc("%d", &dp[0][i][j]); sort(a + 1, a + n + 1, [](Pair q, Pair w) { return q.second < w.second; }); for (int i = 1; i <= n; i++) b[i] = a[i].second; Flody(); while (q--) { int u, v, k; sc("%d%d%d", &u, &v, &k); k = upper_bound(b + 1, b + 1 + n, k) - b - 1; pr("%lld\n", dp[k][u][v]); } } }