「题解」洛谷 P1613 跑路

题目

P1613 跑路

简化题意

给你一个图,你可以在一秒内移动 \(2 ^ i\) 个单位,问你从 \(1\)\(n\) 最少需要多长时间

思路

倍增?

\(f[i][j][k]\) 表示从 \(i\)\(j\) 是否存在一条长为 \(2 ^ k\) 的路径。

用 类似 \(Floyd\) 和倍增的方法可以更新出所有的 \(f\) 数组。

然后就可以再跑一遍 \(Floyd\) 来求最短时间。

Code

#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>

int n, m, f[51][51][41];
int map[51][51];

int main() {
    memset(map, 0x3f3f3f, sizeof map);
    scanf("%d %d", &n, &m);
    for (int i = 1, u, v; i <= m; ++i) {
        scanf("%d %d", &u, &v);
        f[u][v][0] = 1;
        map[u][v] = 1;
    }
    for (int k = 0; k <= 40; ++k) {
        for (int t = 1; t <= n; ++t) {
            for (int i = 1; i <= n; ++i) {
                for (int j = 1; j <= n; ++j) {
                    if (f[i][t][k] && f[t][j][k]) {
                        f[i][j][k + 1] = 1;
                        map[i][j] = 1;
                    }
                }
            }
        }
    }
    for (int k = 1; k <= n; ++k) {
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= n; ++j) {
                if (map[i][j] > map[i][k] + map[k][j]) {
                    map[i][j] = map[i][k] + map[k][j];
                }
            }
        }
    }
    std::cout << map[1][n] << '\n';
    return 0;
}
posted @ 2020-08-26 19:53  yu__xuan  阅读(124)  评论(0编辑  收藏  举报