「题解」洛谷 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;
}