洛谷 2966 2966 [USACO09DEC]牛收费路径Cow Toll Paths

时间:2023-03-09 01:56:40
洛谷 2966 2966 [USACO09DEC]牛收费路径Cow Toll Paths

洛谷 2966 2966 [USACO09DEC]牛收费路径Cow Toll Paths

【题意概述】

  给出一个图,点有正点权,边有正边权,通过两点的代价为两点间的最短路加上路径通过的点的点权最大值。

  有M个询问,每次询问通过两点的代价。

【题解】

  先把点按照点权从小到大排序,然后按照这个顺序跑floyed.  这样的话当前路径i-->k-->j的点权最大值只会在i,j,k中产生,用一个ans[i][j]数组维护代价即可。

 #include<cstdio>
#include<algorithm>
#include<cstring>
#define LL long long
#define rg register
#define N 300
using namespace std;
int n,m,q,f[N][N],ans[N][N],poi[N];
struct rec{
int c,num;
}a[N];
inline int read(){
int k=,f=; char c=getchar();
while(c<''||c>'')c=='-'&&(f=-),c=getchar();
while(''<=c&&c<='')k=k*+c-'',c=getchar();
return k*f;
}
inline void Pre(){
for(rg int i=;i<=n;i++)
for(rg int j=;j<=n;j++) f[i][j]=ans[i][j]=1e9;
for(rg int i=;i<=n;i++) f[i][i]=ans[i][i]=;
}
inline int mx(int a,int b,int c){
int t=-2e9;
if(a>t)t=a;
if(b>t)t=b;
if(c>t)t=c;
return t;
}
inline bool cmp(rec a,rec b){return a.c<b.c;}
int main(){
n=read(); m=read(); q=read();
Pre();
for(rg int i=;i<=n;i++) a[i].c=read(),a[i].num=i;
sort(a+,a++n,cmp);
for(rg int i=;i<=m;i++){
int u=read(),v=read();
f[u][v]=f[v][u]=min(f[u][v],read());
}
for(rg int k=;k<=n;k++)
for(rg int i=;i<=n;i++)
for(rg int j=;j<=n;j++){
int K=a[k].num,I=a[i].num,J=a[j].num;
f[I][J]=f[J][I]=min(f[I][J],f[I][K]+f[K][J]);
ans[I][J]=ans[J][I]=min(ans[I][J],f[I][J]+mx(a[i].c,a[j].c,a[k].c));
}
while(q--){
int u=read(),v=read();
printf("%d\n",ans[v][u]);
}
return ;
}