「題解」洛谷 P1613 跑路
阿新 • • 發佈:2020-08-26
題目
簡化題意
給你一個圖,你可以在一秒內移動 \(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; }