洛谷1613 跑路 倍增 + Floyd

首先,我们一定要认识到本题中的最短时间所对应的道路不一定是在起点到终点的最短路。例如,起点到终点的最短路为 15 15 15 ,那么对 15 15 15 进行二进制拆分的话是 1111 1111 1111 ,这时求出的最短时间为4。然而如果有一条长度为 16 16 16 的路径的话最短时间就为 1 1 1,显然比之前求的更优 。
我们在这里定义两个数组:

  1. i n t int int d [ i ] [ j ] d[i][j] d[i][j],即代表点 ( i , j ) (i,j) (i,j) 之间的最短跑步时间。
  2. b o o l bool bool g [ i ] [ j ] [ k ] g[i][j][k] g[i][j][k],它代表的是点 ( i , j ) (i,j) (i,j) 之间是否有一条跑步时间为 2 k 2^k 2k 的一条道路。
    我们对 g [ i ] [ j ] [ k ] g[i][j][k] g[i][j][k] 运行一遍 F l o y d Floyd Floyd 来更新。
    更新方程是:
    i f ( g [ i ] [ k ] [ l o g − 1 ] if(g[i][k][log-1] if(g[i][k][log1] && g [ k ] [ j ] [ l o g − 1 ] ) g[k][j][log-1]) g[k][j][log1]) g [ i ] [ j ] [ l o g ] = 1 g[i][j][log]=1 g[i][j][log]=1 d [ i ] [ j ] = 1 d[i][j]=1 d[i][j]=1.

显然,我们处理完 g g g 数组后所有可以在一秒之内到达的点对都已处理完毕。于是我们在图上对 d [ i ] [ j ] d[i][j] d[i][j] 再跑一遍 F l o y d Floyd Floyd 即可。
时间复杂度为 O ( n 3 l o g m ) O(n^3logm) O(n3logm)

#include<cstdio>
#include<algorithm>
using namespace std;
const int logn = 60;
const int maxm = 500000 + 5;
const int maxn = 60;
const int inf  = 100000000;
int d[maxn][maxn];
bool g[maxn][maxn][logn];
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i = 1; i <= n;++i)
       for(int j = 1;j <= n;++j)d[i][j] = inf;
    for(int i = 1;i <= m;++i)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        d[a][b] = 1, g[a][b][0] = 1;
    }
    for(int p = 1; p < logn; ++p)
        for(int k = 1; k <= n;++k)
            for(int i = 1; i <= n; ++i)
                for(int j = 1; j <= n;++j)
                {
                    if(g[i][k][p-1] && g[k][j][p-1]) g[i][j][p] = 1, d[i][j] = 1;
                }
    for(int k = 1;k <= n;++k)
        for(int i = 1;i <= n;++i)
            for(int j = 1;j <= n;++j)
                d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
    printf("%d",d[1][n]);
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值