zoukankan      html  css  js  c++  java
  • 洛谷1613 跑路 倍增 + Floyd

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

    1. intint d[i][j]d[i][j],即代表点 (i,j)(i,j) 之间的最短跑步时间。
    2. boolbool g[i][j][k]g[i][j][k],它代表的是点 (i,j)(i,j) 之间是否有一条跑步时间为 2k2^k 的一条道路。
      我们对 g[i][j][k]g[i][j][k] 运行一遍 FloydFloyd 来更新。
      更新方程是:
      if(g[i][k][log1]if(g[i][k][log-1] && g[k][j][log1])g[k][j][log-1]) g[i][j][log]=1g[i][j][log]=1d[i][j]=1d[i][j]=1.

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

    #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;
    }
    
  • 相关阅读:
    解决Ubuntu下gedit中文乱码
    Linux下安装Matlab软件
    3.5mm耳机/麦克接头
    IIS无法加载PHP.ini
    修改mysql用户密码
    dhtmlxgrid使用基础
    远程桌面“终端服务器超出了最大允许连接数”的解决
    MATLAB中格式化M文件注释
    MATLAB中使用Cell对M文件分节
    MATLAB下一些常用易忘命令
  • 原文地址:https://www.cnblogs.com/guangheli/p/9845116.html
Copyright © 2011-2022 走看看