floyd 算法——P1119 灾后重建

floyd 算法

是图论中较为简单的最短路算法,但在某些方面远超最短路范围。

算法思路

定义 f[x][y]xy 节点的最短路径。

初始化:若存在边 (x,y)f[x][y] 等于边长度;若不存在,为 +

特别的,f[x][x]=0

我们考虑一下,x,y 这两个节点通过节点 k 来更新最短路径。

那么有 f[x][y]=min(f[x][k]+f[k][y],f[x][y])

比较好理解,就是到 k 的两条路径相加。

这时可能 f 数组还不是最短路径,但无伤大雅,后面我们会更新到。

比较草率,上代码吧。

for (k = 1; k <= n; k++) {
  for (x = 1; x <= n; x++) {
    for (y = 1; y <= n; y++) {
      f[x][y] = min(f[x][y], f[x][k] + f[k][y]);
    }
  }
}

例题

P1119 灾后重建

思路

floyd 第一层 k 的循环的含义是通过前 k 个点可以转移到的最短路径。

我们将点按修复时间排序即可。

#include<bits/stdc++.h>
using namespace std;

const int maxm=1e5+5,maxn=205;

int n,m,q;
int dis[maxn][maxn],T[maxn];

pair<int,int>vex[maxm];

int now=0,k=1;
void fly()
{
    for(;vex[k].first<=now&&k<=n;k++)
    {
        int K=vex[k].second;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(dis[i][K]+dis[j][K]<dis[i][j]) dis[i][j]=dis[j][i]=dis[i][K]+dis[j][K];
            }
        }
    }
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) dis[i][j]=1e9;
    for(int i=1;i<=n;i++) scanf("%d",&vex[i].first),vex[i].second=i,dis[i][i]=0,T[i]=vex[i].first;
    for(int i=1;i<=m;i++)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        x++,y++;
        dis[x][y]=dis[y][x]=z;
    }

    sort(vex+1,vex+n+1);
    fly();
    scanf("%d",&q);
    while(q--)
    {
        int x,y,t;
        scanf("%d%d%d",&x,&y,&t);
        x++,y++;
        if(T[x]>t||T[y]>t){printf("-1\n");continue;}
        if(now<t)
        {
            now=t;
            fly();
        }
        if(dis[x][y]==dis[0][0]) printf("-1\n");
        else printf("%d\n",dis[x][y]);
    }
}
posted @   彬彬冰激凌  阅读(22)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示