Geodetic
链接:https://ac.nowcoder.com/acm/contest/878/I
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld
U(2,5)=6+2+7+4=19
U(1,5)=1+2+4=7
输入描述:
The first line contains two integers n and
m (3<=n<=200,1<=m<=n*(n-1)/2)—the number of points and the number
of edges. The second line contains n integers, w1, w2, w3,…,wn(1<=wi<=1e6).
The next m lines, two integers x and y per line, indicate that there is an
undirected edge between x and y with a length of 1. The next line is a integer
q(1<=q<=1e5)-the number of questions, the next q lines, two integers x
and y per line, indicate a question.
输出描述:
q lines, one integer per line.
输入
5 6
1 6 2 7 4
1 2
1 3
2 3
2 4
3 5
4 5
3
2 5
5 1
2 4
输出
19
7
13
题目大意:给你n个点的权值,接下来m条道路相连,然后q次询问:x,y 让你输出x到y的最短路径上的所有点的权值之和(注意有可能x到y有多条最短路)。
。。。。比赛的时候一下子就滚出弗洛伊德算法了。。。但可惜的是我一直想通过一遍floyd来解决问题。。。然后就没了。。。暴搜的时候脑子一片混乱。。。
我们可以先用floyd求出所有的点到点的最短距离,然后我们再次使用floyd(不过要小小地改动一下)我们对于任意给定两点(i,j),枚举第三点k,看f[i][j]是否等于f[i][k]+f[k][j],等于那么说明k符合条件,我们直接将ans[i][j]+a[k]就行了。。。
比起暴搜而言更容易写,代码量小,速度也很快。。。
以下是AC代码:
#include <bits/stdc++.h>
using namespace std;
const int inf=1e7+10;
struct node
{
int w,id;
}a[210];
int dis[210][210],ans[210][210];
int main()
{
int n,m;
scanf ("%d%d",&n,&m);
for (int i=1; i<=n; i++)
for (int j=1; j<=n; j++)
dis[i][j]=inf;
for (int i=1; i<=n; i++){
scanf ("%d",&a[i].w);
a[i].id=i;
dis[i][i]=0;
}
int x,y;
for (int i=1; i<=m; i++){
scanf ("%d%d",&x,&y);
dis[x][y]=dis[y][x]=1;
}
for (int k=1; k<=n; k++)
for (int i=1; i<=n; i++)
for (int j=1; j<=n; j++){
if (dis[i][k]+dis[k][j]<dis[i][j]){
dis[i][j]=dis[i][k]+dis[k][j];
}
}
for (int i=1; i<=n; i++)
for (int j=1; j<=n; j++)
for (int k=1; k<=n; k++){
if (dis[i][k]+dis[k][j]==dis[i][j]){
ans[i][j]+=a[k].w;
}
}
int q;
scanf ("%d",&q);
for (int i=1; i<=q; i++){
scanf ("%d%d",&x,&y);
printf ("%d\n",ans[x][y]);
}
return 0;
}