题目链接 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;
}