Shortest Path
Accepts: 40
Submissions: 610
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
这道题刚开始想要建立一个二维的dis来装下所有点到所有点之间的距离,但是最后发现直接都不能编译,太大了。。。。。。。。
所以看了比赛完后的解题思路以及其他人的代码,才明白了原来可以只存下改变的6个点之间任意两点间的距离
#include <iostream>
#include<cstdio>
#include<cmath>
using namespace std;
#define mm 1000000007
#define ll long long
int dis[10][10];
int main()
{
int t,n,m,x,y;
int a[10];
scanf("%d",&t);
while(t--)
{
long long ans=0;
int dist;
scanf("%d%d",&n,&m);
for(int i=1;i<=6;i++)
scanf("%d",&a[i]);
for(int i=1;i<=6;i++)
for(int j=1;j<=6;j++)
{
dis[i][j]=dis[j][i]=abs(a[i]-a[j]);
}
for(int i=1;i<=6;i+=2)
dis[i][i+1]=dis[i+1][i]=1;
for(int k=1;k<=6;k++)
for(int i=1;i<=6;i++)
for(int j=1;j<=6;j++)
{
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
for(int k=1;k<=m;k++)
{
scanf("%d%d",&x,&y);
dist=abs(x-y);
for(int i=1;i<=6;i++)
for(int j=1;j<=6;j++)
{
dist=min(dist,abs(x-a[i])+dis[i][j]+abs(y-a[j]));
}
ans+=(ll)k*dist; //ll很必要
ans%=mm;
}
printf("%I64d\n",ans%mm);
}
return 0;
}