跑路
跑路
一、题目理解与分析
1. 题意转化
最后我已经处理完了这个路径,并得到了一个距离 \(L\) ,最后我需要的就是关于 \(L\) 的拆分:
$ L = 2^{k1} + 2^{k2} + ··· + 2^{k_i} $
最后我要输出的是 \(i\) 的最小值
2. 最终思考
最后我的得到的 L 转换成二进制时,所含1的个数必须最少
二、算法设计
核心思想:倍增 + dfs
Step1:倍增预处理
vis[i][j][k] = true //这个表示从点 i 到点 j 有恰好长度为2的k次方的路径
初始状态定义:
- 若存在边
i => j,则定义:vis[i][j][0] = ture
Step2 状态转移:
**可能存在几个中间点 $ mid_1,mid_2,···,mid_n$ **
-
有从
i到 \(mid_i\) 有一条长度为 $ 2 ^ {k-1} $ 的路径 -
有从 \(mid_i\) 到
j有一条长度为 $ 2 ^ {k-1} $ 的路径
Step3 BFS的引入:
运用BFS,从1到n,每次移动约等于用一次跑路器
求到的最短路径长度处理后就等于最少秒数(最终需要最优策略)
三、代码:此处为AI填写注释,有不懂的立马询问台上讲题者/论坛内询问
#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
vector<int> mp[55]; // 邻接表存原图
int n, m;
int step[55]; // BFS距离数组
bool vis[55][55][55]; // 核心状态数组
int main() {
// 输入
cin >> n >> m;
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
mp[u].push_back(v);
vis[u][v][0] = true; // 初始:直接相邻
}
// 第一部分:倍增预处理
// 为什么 k 到 32?
// maxlongint ≈ 2^31,所以 2^k 最大到 2^31,k最大31
// 取32更安全
for (int k = 1; k <= 32; k++) {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
// 枚举所有可能的中间点
for (int mid = 1; mid <= n; mid++) {
// 如果 i->mid 和 mid->j 都有 2^{k-1} 的路径
// 那么 i->j 就有 2^k 的路径
if (vis[i][mid][k-1] && vis[mid][j][k-1]) {
vis[i][j][k] = true;
}
}
}
}
}
// 第二部分:BFS求最少秒数
memset(step, 0x3f, sizeof(step));
step[1] = 0;
queue<int> q;
q.push(1);
while (!q.empty()) {
int u = q.front();
q.pop();
// 尝试所有可能的 2^k 跳转
for (int k = 0; k <= 32; k++) {
for (int v = 1; v <= n; v++) {
// 如果 u 可以 1 秒到 v,且可以更新距离
if (vis[u][v][k] && step[v] > step[u] + 1) {
step[v] = step[u] + 1;
q.push(v);
}
}
}
}
// 输出结果
cout << step[n] << endl;
return 0;
}
四、复杂度分析
PART 1 时间复杂度
1.预处理部分
三层n循环+一层32循环
总复杂度为$ O(32 \times n^3)$
2.BFS
两层n循环+一层32循环
总复杂度\(O(32\times n^2)\)
总复杂度
$ O(max(32 \times n^3,32\times n^ 2)) = O(32 \times n^3)$
题目限制条件中 $ n \le 50 $ ,完全可行
PART 2 空间复杂度
vis: $ n^2 \times 55 $ 一个M都没到,可行!
五、常见疑问
Q1:为什么k的max可以取到 $ {32} $ ,longint不是 \({31}\) 吗?
A:取到\(32\)可以理解为缓冲,不会影响最终结果
Q2:自环的作用是什么?
A:例如样例中的1=>1,重构路径长度为\(2^k\),得到最优解
Q3:为什么 BFS 中要检查所有 k?
A:从u到v可以有最多$ 2^k\(的方式到达,所以说我们知道了这个路径为\) 2^k$那么我们就可以知道这个时间是1s,与k无关,只是进行计算罢了
Q4:重边处理
A:用vis数组表示,重边也不影响结果
©2025 WJW all right reserved

浙公网安备 33010602011771号