HDU 5636 Shortest Path(Floyd)
题目链接 HDU5636
n个点,其中编号相邻的两个点之间都有一条长度为1的边,然后除此之外还有3条长度为1的边。
m个询问,每次询问求两个点之前的最短路。
我们把这三条边的6个点两两算最短路,
然后询问的时候用这6个点的距离来更新答案就可以了。
(不过听说好像有更好的方法,先占个坑)
时间复杂度$O(216m)$
#include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i) #define dec(i, a, b) for (int i(a); i >= (b); --i) typedef long long LL; const LL mod = 1e9 + 7; int T; int n, m; int a[10]; int b[10][10]; int d; LL ans, cnt; int main(){ scanf("%d", &T); while (T--){ scanf("%d%d", &n, &m); rep(i, 1, 6) scanf("%d", a + i); ans = 0; cnt = 0; rep(i, 1, 6) rep(j, 1, 6) b[i][j] = abs(a[i] - a[j]); b[1][2] = b[2][1] = 1; b[3][4] = b[4][3] = 1; b[5][6] = b[6][5] = 1; rep(k, 1, 6) rep(i, 1, 6) rep(j, 1, 6) b[i][j] = min(b[i][j], b[i][k] + b[k][j]); for (; m--; ){ scanf("%d%d", &a[7], &a[8]); d = abs(a[7] - a[8]); rep(i, 1, 6) rep(j, 1, 6) d = min(d, abs(a[i] - a[7]) + abs(a[j] - a[8]) + b[i][j]); (ans += (++cnt) * (LL)d) %= mod; } printf("%lld\n", ans); } return 0; }