过路费【Floyd】

题目大意:
这里写图片描述


思路:
emm给你们讲一个故事,FloydSPFA快。

啥,不信?那就随你喽。

某dalao的感人事迹,上面是Floyd,下面是SPFA
这里写图片描述

这道题真的没想到是用Floyd,而且这题卡了我3小时。。。

哇我被Floyd卡了三小时我好菜啊

进入正题。

这道题用Floyd的好处是,Floyd点排序后可以直接一边处理最短路,一边可以处理最短路上点最大值。

所以,我们要先将点按权值从小到大排一次序,那么在num[i]num[j]num[k]中总有一个是最大值。

所以,我们跑一边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;
}
posted @ 2018-07-09 07:55  全OI最菜  阅读(121)  评论(0编辑  收藏  举报