【题意概述】
给出一个图,点有正点权,边有正边权,通过两点的代价为两点间的最短路加上路径通过的点的点权最大值。
有M个询问,每次询问通过两点的代价。
【题解】
先把点按照点权从小到大排序,然后按照这个顺序跑floyed. 这样的话当前路径i-->k-->j的点权最大值只会在i,j,k中产生,用一个ans[i][j]数组维护代价即可。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #define LL long long 5 #define rg register 6 #define N 300 7 using namespace std; 8 int n,m,q,f[N][N],ans[N][N],poi[N]; 9 struct rec{ 10 int c,num; 11 }a[N]; 12 inline int read(){ 13 int k=0,f=1; char c=getchar(); 14 while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); 15 while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar(); 16 return k*f; 17 } 18 inline void Pre(){ 19 for(rg int i=0;i<=n;i++) 20 for(rg int j=0;j<=n;j++) f[i][j]=ans[i][j]=1e9; 21 for(rg int i=0;i<=n;i++) f[i][i]=ans[i][i]=0; 22 } 23 inline int mx(int a,int b,int c){ 24 int t=-2e9; 25 if(a>t)t=a; 26 if(b>t)t=b; 27 if(c>t)t=c; 28 return t; 29 } 30 inline bool cmp(rec a,rec b){return a.c<b.c;} 31 int main(){ 32 n=read(); m=read(); q=read(); 33 Pre(); 34 for(rg int i=1;i<=n;i++) a[i].c=read(),a[i].num=i; 35 sort(a+1,a+1+n,cmp); 36 for(rg int i=1;i<=m;i++){ 37 int u=read(),v=read(); 38 f[u][v]=f[v][u]=min(f[u][v],read()); 39 } 40 for(rg int k=1;k<=n;k++) 41 for(rg int i=1;i<=n;i++) 42 for(rg int j=1;j<=n;j++){ 43 int K=a[k].num,I=a[i].num,J=a[j].num; 44 f[I][J]=f[J][I]=min(f[I][J],f[I][K]+f[K][J]); 45 ans[I][J]=ans[J][I]=min(ans[I][J],f[I][J]+mx(a[i].c,a[j].c,a[k].c)); 46 } 47 while(q--){ 48 int u=read(),v=read(); 49 printf("%d ",ans[v][u]); 50 } 51 return 0; 52 }