目录:
题目:
分析:
看完题目,我们很容易想到使用
算法,在时间上n<=250,可以通过,但
中参加运算的只有边权,可这道题目偏偏还要个点权,我们不妨建两个数组,一个用来保存
的结果,另一个是在
的基础上加上最大的点权
对此,我们可以提前对点权进行从小到大的排序,在
时,最大的点权就会在i,j,k中产生
这是因为我们在之前从小到大排序了,而i,j,k中的某一个肯定是在i到j这条路径上最大的(请消化消化)
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define LL long long
using namespace std;
inline LL read()
{
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
struct node{
int x,y;
}x[251];
int newid[251];
int f[251][251],ans[251][251];
bool cmd(node a,node b)
{
return a.x<b.x;
}
int min(int a,int b)
{
return a<b? a:b;
}
int max(int a,int b)
{
return a>b? a:b;
}
int main()
{
freopen("toll.in","r",stdin);
freopen("toll.out","w",stdout);
int n=read(),m=read(),q=read();
for(int i=1;i<=n;i++)
x[i].x=read(),x[i].y=i;
sort(x+1,x+1+n,cmd);
for(int i=1;i<=n;i++) newid[x[i].y]=i;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
f[i][j]=ans[i][j]=99999999;
int a,b,w;
for(int i=1;i<=m;i++)
{
a=newid[read()];b=newid[read()];w=read();
f[a][b]=f[b][a]=min(w,f[a][b]);
}
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],f[i][k]+f[k][j]);
ans[i][j]=min(ans[i][j],f[i][j]+max(x[k].x,max(x[i].x,x[j].x)));
}
for(int i=1;i<=q;i++)
{
a=read();b=read();
printf("%d\n",ans[newid[a]][newid[b]]);
}
fclose(stdin);
fclose(stdout);
return 0;
}