题目描述
旅行是一件颇有趣的事情,但是在旅行前规划好路线也很重要。
现在小D计划要去U国旅行。
U国有N个城市,M条道路,每条道路都连接着两个城市,并且经过这条道路需要一定的费用wi。
现在小D想要从u城市到v城市,但是他的汽车需要在途中加一次油(途中包括u和v两个城市)。在每个城市加油都有不同的费用vi。
小D想知道从u城市到v城市最少需要多少费用(经过道路的费用+加油的费用)。
城市从1-n进行编号。
格式
输入格式
第一行两个正整数n,m,表示n个城市,m条无向道路
接下来n行,第i行一个整数vi,表示第i个城市的加油费用
接下来m行,第i行三个整数ai, bi, wi,表示第i条道路连接ai和bi两个城市,经过要花费wi的费用
接下来一个正整数q,表示小D有q个询问
接下来q行,第i行两个整数ui, vi, 表示小D想知道从ui到vi需要的最少费用(ui和vi可能相等)
输出格式
对于每个询问,输出一行整数,表示最小的费用,如果ui不能到达vi,则输出-1
样例1
样例输入1
3 6
2666
3977
2457
1 2 6920
1 2 276
1 3 839
3 1 3490
2 1 7395
3 1 7540
6
3 2
3 1
2 2
2 1
3 2
2 2
样例输出1
3572
3296
3218
2942
3572
3218
限制
每个测试点1s
提示
对于30%的数据,保证n<=10
对于70%的数据,保证n<=80
对于100%的数据,保证n<=300
保证q,m<=n*n, 0 <= wi, vi <= 10000
数据中可能有重边和自环
一个最短路的水题。
先跑一边floyd求出每个点之间的最短路径,然后再枚举每一个点作为加油站时的最小花费就行了 。
#include<bits/stdc++.h>
using namespace std;
const int inf=1e8;
const int N=310;
int n,m,q,g[N][N],f[N][N],w[N];
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) g[i][j]=f[i][j]=inf;
for(int i=1;i<=n;i++) cin>>w[i],g[i][i]=0;
while(m--)
{
int a,b,w;
cin>>a>>b>>w;
g[a][b]=g[b][a]=min(g[a][b],w);
}
for(int k=1;k<=n;k++)//floyd
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
f[i][j]=min(f[i][j],w[k]+g[i][k]+g[k][j]);//当k点为加油站时
cin>>q;
while(q--)
{
int a,b;
cin>>a>>b;
cout<<f[a][b]<<endl;
}
return 0;
}