Shortest Path
Accepts: 80
Submissions: 431
Time Limit: 4000/2000 MS (Java/Others)
Memory Limit: 131072/131072 K (Java/Others)
问题描述
有一条长度为n的链. 节点i和i+1之间有长度为1的边. 现在又新加了3条边, 每条边长度都是1. 给出m个询问, 每次询问两点之间的最短路.
输入描述
输入包含多组数据. 第一行有一个整数T, 表示测试数据的组数. 对于每组数据: 第一行包含2个整数n和m (1≤n,m≤105)表示节点的数目和询问数目. 接下来一行包含6个有空格分开的整数a1,b1,a2,b2,a3,b3 (1≤a1,a2,a3,b1,b2,b3≤n), 表示新加的三条边为(a1,b1), (a2,b2), (a3,b3). 接下来m行, 每行包含两个整数si和ti (1≤si,ti≤n), 表示一组询问. 所有数据中m的和不超过106.
输出描述
对于每组数据, 输出一个整数S=(i=1∑mi⋅zi) mod (109+7), 其中zi表示第i组询问的答案.
输入样例
1 10 2 2 4 5 7 8 10 1 5 3 1
输出样例
7
添加三条边,然后再“硬算”,要考虑很多种情况。
对添加的6个点floyd算出最短距离,然后对每对u,v,枚举中间的两个点。
代码:
#pragma warning(disable:4996)
#include <iostream>
#include <functional>
#include <algorithm>
#include <cstring>
#include <vector>
#include <string>
#include <cstdio>
#include <cmath>
#include <queue>
#include <stack>
#include <deque>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
#define INF 0x3fffffffffffffff
const ll mod = 1e9 + 7;
const int maxn = 1e5 + 5;
int n, m;
int a[10], b[10];
int dis[10][10];
int getpos(int x)
{
return lower_bound(a + 1, a + 6 + 1, x) - a;
}
void solve()
{
int i, j, k;
int x1, x2, u, v;
scanf("%d%d", &n, &m);
for (i = 1; i <= 6; i++)
{
scanf("%d", &a[i]);
b[i] = a[i];
}
sort(a + 1, a + 6 + 1);
for (i = 1; i <= 6; i++)
{
for (j = 1; j <= 6; j++)
{
dis[i][j] = abs(a[i] - a[j]);
}
}
x1 = getpos(b[1]);
x2 = getpos(b[2]);
dis[x1][x2] = dis[x2][x1] = min(dis[x1][x2], 1);
x1 = getpos(b[3]);
x2 = getpos(b[4]);
dis[x1][x2] = dis[x2][x1] = min(dis[x1][x2], 1);
x1 = getpos(b[5]);
x2 = getpos(b[6]);
dis[x1][x2] = dis[x2][x1] = min(dis[x1][x2], 1);
//做的时候没有注意到这里。。。
for (k = 1; k <= 6; k++)
{
for (i = 1; i <= 6; i++)
{
for (j = 1; j <= 6; j++)
{
dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
}
}
}
ll ans = 0;
for (k = 1; k <= m; k++)
{
scanf("%d%d", &u, &v);
ll res = abs(u - v);
for (i = 1; i <= 6; i++)
{
for (j = 1; j <= 6; j++)
{
res = min(res, (ll)(abs(u - a[i]) + abs(v - a[j]) + dis[i][j]));
}
}
ans = (ans + (ll)(res*k)%mod) % mod;
}
printf("%lld\n", ans);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("i.txt", "r", stdin);
freopen("o.txt", "w", stdout);
#endif
int t;
scanf("%d", &t);
while (t--)
{
solve();
}
return 0;
}