过路费【Floyd】
题目大意:
思路:
emm给你们讲一个故事,比快。
啥,不信?那就随你喽。
某dalao的感人事迹,上面是,下面是。
这道题真的没想到是用,而且这题卡了我3小时。。。
哇我被Floyd卡了三小时我好菜啊
进入正题。
这道题用的好处是,点排序后可以直接一边处理最短路,一边可以处理最短路上点最大值。
所以,我们要先将点按权值从小到大排一次序,那么在,,中总有一个是最大值。
所以,我们跑一边,最短路和点权一起处理,就可以求出真正的最短路了。
代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int n,m,x,y,z,t,d[501][501],dis[501][501],o[501];
int num[501],ak[501];
bool cmp(int x,int y)
{
return num[x]<num[y];
}
void fre()
{
freopen("toll.in","r",stdin);
freopen("toll.out","w",stdout);
}
int main()
{
fre();
scanf("%d%d%d",&n,&m,&t);
for (int i=1;i<=n;i++)
{
scanf("%d",&num[i]);
ak[i]=i;
}
memset(d,127/3,sizeof(d));
memset(dis,127/3,sizeof(dis)); //初始化
for (int i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&z);
d[x][y]=d[y][x]=min(d[x][y],z);
}
sort(ak+1,ak+1+n,cmp); //按点权排序
for (int kk=1;kk<=n;kk++) //Floyd
{
int k=ak[kk];
for (int i=1;i<=n;i++)
{
for (int j=1;j<=n;j++)
{
if (i!=j&&j!=k&&k!=i)
{
d[i][j]=min(d[i][j],d[i][k]+d[k][j]); //求最短路
dis[i][j]=min(dis[i][j],d[i][j]+max(num[i],max(num[j],num[k]))); //求加点权的最短路
}
}
}
} //初始化结束
for (int i=1;i<=t;i++) //O(1)输出
{
scanf("%d%d",&x,&y);
printf("%d\n",dis[x][y]);
}
return 0;
}