题意:有一条长度为
n
的链. 节点
思路:
s−t
的最短路只有两种可能。
(1)
经过特殊的
6
个点;
对于情况
(1)
,我们考虑经过多少个点。经过一个点,直接枚举就好了;经过两个点同样枚举;经过三个点和经过两个点本质是一样的。这样只需枚举一个点和两个点的情况即可。
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#define CLR(a, b) memset(a, (b), sizeof(a))
using namespace std;
typedef long long LL;
const int MAXN = 1e5+10;
const int INF = 0x3f3f3f3f;
const double eps = 1e-4;
const int MOD = 1e9+7;
int dist[6][6];
int num[6];
int u[6], v[6];
int main()
{
int t; scanf("%d", &t);
while(t--)
{
int n, m; scanf("%d%d", &n, &m);
int top = 0;
for(int i = 1; i <= 3; i++)
{
scanf("%d%d", &u[i], &v[i]);
num[top++] = u[i]; num[top++] = v[i];
}
for(int i = 0; i < 6; i++)
for(int j = 0; j < 6; j++)
dist[i][j] = abs(num[i]-num[j]);
top = 0;
for(int i = 1; i <= 3; i++)
dist[top][top+1] = dist[top+1][top] = min(1, dist[top][top+1]), top += 2;
for(int k = 0; k < 6; k++)
for(int i = 0; i < 6; i++)
for(int j = 0; j < 6; j++)
dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
LL ans = 0;
for(int k = 1; k <= m; k++)
{
int s, t;
scanf("%d%d", &s, &t);
int res = abs(s-t);
for(int i = 0; i < 6; i++)
{
for(int j = 0; j < 6; j++)
{
res = min(res, abs(s-num[i]) + abs(t-num[j]) + dist[i][j]);
res = min(res, abs(s-num[j]) + abs(t-num[i]) + dist[i][j]);
}
}
//cout << res << endl;
ans = (ans + 1LL * res * k % MOD) % MOD;
}
cout << ans << endl;
}
return 0;
}