灾后重建(对Floyd的认识)

传送门

主要考察了对Floyd算法的认识程度(告诉我们背板子是不行的)。

Floyd,代码很简单,而其本质思想是通过其他的点进行中转来求的两点之间的最短路。因为我们知道,两点之间有多条路,如果换一条路可以缩短距离的话,就更新最短距离。而它最本质的思想,就是用其他的点进行中转,从而达到求出最短路的目的。(精辟总结摘自洛谷题解)。

对于这道题,要求得任意两点间的最短路,但是可以用来做中转点的点确实不定的。

我们可以对于每次因时间增加而加入的新的可以做中转点的点,运用Floyd的本质解题。

题目保证t0t1tN1​,而后面询问里给出的t也保证了t是不下降的。所以顺着加就好了。

注意:序号是从0开始的

#include<bits/stdc++.h>
#define N 202
#define INF 2100000001
#define LL long long
using namespace std;
int read()
{
    int x=0,f=1;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    return x*f;
}
int t[N];LL f[N][N];
int n,m;
void update(int k)
{
    for(int i=0;i<n;++i)
      for(int j=0;j<n;++j)
        if(f[i][k]+f[k][j]<f[i][j])
          f[i][j]=f[j][i]=f[i][k]+f[k][j];
}
int main()
{
    n=read(),m=read();
    for(int i=0;i<n;++i)t[i]=read();
    for(int i=0;i<n;++i)
      for(int j=i+1;j<n;++j)
      {
          if(i!=j)
          {
              f[i][j]=INF;
              f[j][i]=INF;
        }
      }
    for(int i=1;i<=m;++i)
    {
        int a=read(),b=read(),c=read();
        f[a][b]=f[b][a]=c;
    } 
    int q=read();
    int now=0;
    while(q--)
    {
        int a=read(),b=read(),time=read();
        while(t[now]<=time&&now<n)update(now),now++;
        if(t[a]>time||t[b]>time||f[a][b]==INF)printf("-1
");
        else printf("%lld
",f[a][b]);
    }
} 
View Code
原文地址:https://www.cnblogs.com/yyys-/p/11361092.html