• luogu P1613 跑路 题解 (倍增 && 最短路)


    这道题的思路非常巧妙,如果两点之间的距离是$2^k$,那么就建一条长度为1的边,然后再跑一遍最短路就好了。

    推的方法就是$f(i, j, len) = 1$ 如果 $f(i, k, len - 1) = 1$ 并且$f(k, j, len - 1) = 1$,其中$f(i, j, len)$指的是$i$到$j$是否有长度为$2^{len}$的边

    有意思的是,如果一条路径是要重复走的,比如$i$和$j$之间有两条边,那么两个$2^0$的边存在,就可以推出$f(i, i)$存在$2^1$的边,可以看出这种情况是不会遗漏的。

    代码如下

    #include <cstdio>
    using namespace std;
    const int N = 51;
    int dis[N][N][N], ans[N][N];
    int main() {
        int n, m;
        scanf("%d %d", &n, &m);
        for (int i = 1; i <= m; i++) {
            int u, v;
            scanf("%d %d", &u, &v);
            dis[u][v][0] = ans[u][v] = 1;
        }
        for (int len = 1; len <= 32; len++)
            for (int k = 1; k <= n; k++)
                for (int i = 1; i <= n; i++)
                    for (int j = 1; j <= n; j++)
                        if (dis[i][k][len - 1] == 1 && dis[k][j][len - 1] == 1)
                            dis[i][j][len] =  1, ans[i][j] = 1;
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++) 
                if (i != j && ans[i][j] != 1)
                    ans[i][j] = (1 << 29);
        for (int k = 1; k <= n; k++)
            for (int i = 1; i <= n; i++)
                for (int j = 1; j <= n; j++)
                    if (ans[i][k] + ans[k][j] < ans[i][j])
                        ans[i][j] = ans[i][k] + ans[k][j];
        printf("%d", ans[1][n]);    
        return 0;        
    }
  • 相关阅读:
    暑假集训每日一题0716(BFS)
    HDOJ1754(I Hate It)
    POJ2777(Count Color)
    暑假集训每日一题0717(DFS)
    SPOJ7259(Light Switching)
    cocos2dx CCTextureCache
    写给自己——EntryName命名规则
    观XX项目感1
    观XX项目感2 之 软件工程的图纸(再看UML类图)
    游戏编程 && cocos2d 学习
  • 原文地址:https://www.cnblogs.com/cminus/p/12492910.html
Copyright © 2020-2023  润新知