[luogu p1613] 跑路
阿新 • • 發佈:2020-11-05
\(\mathtt{Link}\)
\(\mathtt{Summarization}\)
給定一個有向圖 \(G\),進行一次操作可以走 \(2 ^ k\) 條邊,求 \(1 \rightarrow n\) 的最小運算元。
\(\mathtt{Solution}\)
看到一次操作 \(2 ^ k\) 自然想到倍增。
再看到如此弱的資料範圍,\(n \le 50\),一般五層迴圈巢狀都沒問題。
那就可以放心採用這樣一種做法了:
定義一個數組 dir,定義 dir[i][j][k] 為 從 i -> j 是否有一條長度為 \(2 ^ k\) 的路徑。
便可以想到一種暴力倍增的方案:每次列舉 \(k\)
有:
\[dir_{u,i,k-1} = \text{true}, dir_{i, v, k - 1} = \text{true} \rightarrow dir_{u, v, k} = \text{true} \]至於初始條件,顯然:
\[u \rightarrow v \in G \rightarrow dir_{u, v, 0} = \text{true} \]那麼,\(dir\) 和 \(dis\) 之間的關係怎麼求呢?
對於兩個頂點 \(u, v\),若存在一個 \(k\) 使得 \(dir_{u, v, k} = \text{true}\)
最後根據這些 \(dis\) 用 floyd 求最短路即可。
\(\mathtt{Time} \text{ } \mathtt{Complexity}\)
核心倍增複雜度:\(\mathcal{O}(\log dis \times n ^ 3)\)
floyd複雜度:\(\mathcal{O}(n^3)\)
所以整體複雜度是 \(\mathcal{O}(\log dis \times n ^ 3)\)
\(\mathtt{Code}\)
/* * @Author: crab-in-the-northeast * @Date: 2020-11-04 13:55:04 * @Last Modified by: crab-in-the-northeast * @Last Modified time: 2020-11-04 14:09:23 */ #include <iostream> #include <cstdio> #include <cstring> const int maxn = 55; const int maxlogdis = 65; inline int read() { char ch = getchar(); int x = 0, f = 1; while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return x * f; } inline int min(int a, int b) { return a < b ? a : b; } int dis[maxn][maxn]; bool dir[maxn][maxn][maxlogdis]; int main() { std :: memset(dir, 0, sizeof(dir)); std :: memset(dis, maxn, sizeof(dis)); int n = read(), m = read(); for (int i = 1; i <= m; ++i) { int u = read(), v = read(); dis[u][v] = 1; dir[u][v][0] = true; } for (int k = 1; k < maxlogdis; ++k) for (int u = 1; u <= n; ++u) for (int i = 1; i <= n; ++i) for (int v = 1; v <= n; ++v) if (dir[u][i][k - 1] && dir[i][v][k - 1]) { dir[u][v][k] = true; dis[u][v] = 1; } for (int i = 1; i <= n; ++i) for (int u = 1; u <= n; ++u) for (int v = 1; v <= n; ++v) dis[u][v] = min(dis[u][v], dis[u][i] + dis[i][v]); std :: printf("%d\n", dis[1][n]); return 0; }
\(\mathtt{More}\)
看到這種弱資料範圍一定要放心,別想太複雜。