vijos1746 floyd

时间:2023-03-09 15:15:26
vijos1746 floyd

小D的旅行

旅行是一件颇有趣的事情,但是在旅行前规划好路线也很重要。

现在小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可解,主要就是如何判断加油点,一开始写了一个floyd把加油单独存入一个数组结果一直WA。

仔细想想的话假设我们已经知道了任意两点之间的最短距离,那么对于a--->b我们只要枚举出所有可能的加油站就好了哇!  ans=MIN{e[a][k]+e[k][b]+w[k]}

哎还是太笨

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
int e[305][305];
int w[305][305];
int N,M,W[305];
int main()
{
int i,j,q,k;
int a,b,c;
memset(e,inf,sizeof(e));
memset(w,inf,sizeof(w));
cin>>N>>M;
for(i=1;i<=N;++i) scanf("%d",&W[i]),e[i][i]=0;
for(i=1;i<=M;++i){
scanf("%d%d%d",&a,&b,&c);
if(e[a][b]>c) e[a][b]=e[b][a]=c;
}

for(k=1;k<=N;++k)
for(i=1;i<=N;++i)
for(j=1;j<=N;++j)
e[i][j]=min(e[i][j],e[i][k]+e[k][j]);

scanf("%d",&q);
while(q--){int ans=inf;
scanf("%d%d",&a,&b);
for(k=1;k<=N;++k) ans=min(ans,e[a][k]+e[k][b]+W[k]);
printf("%d\n",ans!=inf?ans:-1);
}
return 0;
}