暴力的想法是
[f[i][j]=min{f[i][k]+f[k][j]}\
g[i][j]=f[i][j]+max{val[i],val[j],val[k]}
]
但是这样并不能保证真的取到路径上的点权最大值,Floyd中的k并没有给我们什么好的性质
但是Floyd的拓扑序是人定的,只是习惯从1到(n)而已
因此我们按点权排序,保证点权递增,这个式子就是正确的了
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
inline int rd(){
int ret=0,f=1;char c;
while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
while(isdigit(c))ret=ret*10+c-'0',c=getchar();
return ret*f;
}
#define space putchar(' ')
#define nextline putchar('
')
void _(int x){if(!x)return;_(x/10);putchar('0'+x%10);}
void out(int x){if(!x)putchar('0');_(x);}
const int MAXN = 300;
int f[MAXN][MAXN],g[MAXN][MAXN];
int val[MAXN],id[MAXN];
int n,m,q;
inline void upmin(int &x,int y){x=min(x,y);}
bool cmp(int x,int y){
return val[x]<val[y];
}
int main(){
memset(f,0x3f,sizeof(f));
memset(g,0x3f,sizeof(g));
n=rd();m=rd();q=rd();
for(int i=1;i<=n;i++)val[i]=rd();
int x,y;
for(int i=1;i<=m;i++){
x=rd();y=rd();
f[x][y]=f[y][x]=min(f[x][y],rd());
}
for(int i=1;i<=n;i++)id[i]=i,f[i][i]=0;
sort(id+1,id+1+n,cmp);
for(int _k=1;_k<=n;_k++){
int k=id[_k];
for(int _i=1;_i<=n;_i++){
int i=id[_i];
for(int _j=1;_j<=n;_j++){
int j=id[_j];
upmin(f[i][j],f[i][k]+f[k][j]);
upmin(g[i][j],f[i][j]+max(val[k],max(val[i],val[j])));
}
}
}
for(int i=1;i<=q;i++){
out(g[rd()][rd()]);
nextline;
}
return 0;
}