巧妙的 F l o y d Floyd Floyd
我们先把点权排序,这样就能符合 F l o y d Floyd Floyd的性质,我们就可以直接一边跑 F l o y d Floyd Floyd一边比较点权求最大了。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
int f[1010][1010],w[1010],bq[1010][1010];
int n,m,q,ax,ay,x,y,z;
struct node
{
int c,id;
}d[1010];
bool cmp(node a,node b)
{
return a.c==b.c?a.id<b.id:a.c<b.c;
}
int main()
{
freopen("toll.in","r",stdin);
freopen("toll.out","w",stdout);
cin>>n>>m>>q;
for(int i=1; i<=n; i++)
{
scanf("%lld",&d[i].c);
d[i].id=i;
}
sort(d+1,d+1+n,cmp);
for(int i=1; i<=n; i++)
w[d[i].id]=i;
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
f[i][j]=bq[i][j]=1e9;
for(int i=1; i<=n; i++)
bq[i][i]=0;
for(int i=1; i<=n; i++)
for(int j=1; j<=f[i]; j++)
if(bq[i][j]==w[i])
f[i][j]=bq[i][j]+w[i];
for(int i=1; i<=m; i++)
{
scanf("%lld%lld%lld",&x,&y,&z);
x=w[x];
y=w[y];
bq[x][y]=min(bq[x][y],z); //预处理边权
bq[y][x]=bq[x][y];
}
for(int k=1; k<=n; k++)
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
{
bq[i][j]=min(bq[i][j],bq[i][k]+bq[k][j]); //Floyd
f[i][j]=min(bq[i][j]+max(d[i].c,max(d[j].c,d[k].c)),f[i][j]); //点权比较
}
for(int i=1; i<=q; i++)
{
scanf("%lld%lld",&ax,&ay);
ax=w[ax];
ay=w[ay];
cout<<f[ax][ay]<<endl;
}
return 0;
}