CSES 1667 Message Route 题解
Message Route
题目大意
有 \(n\) 个节点和 m 条无向边,节点编号为 \(1 \sim n\),问节点 \(1\) 和节点 \(n\) 之间是否连通。
- 如连通,输出最短路径长度和任意一条最短路径中包含的所有点
- 如不连通,输出
IMPOSSIBLE
思路
首先,我们要大致了解一下最短路,利用BFS
,我们可以用 O(n + m) 的时间复杂度来求出从 \(1\) 到 \(n\) 的最短路径。
可以用vector
去存储每条边,即邻接表。
BFS
首先,将初始状态加入到队列当中。
- 处理队头,可以转移到许多的点上。
· 先要弹出队头
· 如果当前转移到的点没有被遍历过,那么这个点的最短路径肯定是由队头转移而来。由于要记录路径,那么在这里记录一下这个点是由队头转移而来。
· 如果遍历过了,那么长度肯定不会比当前路径还要短,所以不需要记录。 - 如果队列空了,那么其他没有入过队列的节点肯定与节点 \(1\) 是不连通的。结束
bfs
- 如果队列非空,那么执行操作 \(1\)
最后判断答案,输出答案即可。
路径输出详见代码注释。
Code
点击查看代码
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
const int N = 1e5 + 10;
int n, m, x, y, vis[N], fa[N], q[N], h, t;
vector<int> v[N];
void record (int x_, int x, int lv) { // 处理当前队头转移到的点
if (vis[x]) { // 它已经被遍历过
return ;
}
vis[x] = lv;
q[t++] = x;
fa[x] = x_; // 记录 bfs 树中当前节点的父亲
}
void bfs () {
record(1, 1, 1); // 处理初始状态
while (h < t) {
int _ = q[h++];
for (int i = 0; i < v[_].size(); i++) { // 队头能够转移到的点
record(_, v[_][i], vis[_] + 1);
}
}
}
void Print (int x) { // 输出路径处理
if (x != 1) { // 它不是开始的点
Print(fa[x]); // 先要去遍历它的父亲
}
cout << x << ' '; // 输出当前的点
}
int main(){
cin >> n >> m;
for (int i = 1; i <= m; i++) {
cin >> x >> y;
v[x].push_back(y);
v[y].push_back(x); // 无向图
}
bfs();
if (!vis[n]) { // 非连通
cout << "IMPOSSIBLE";
} else {
cout << vis[n] << '\n';
Print(n);
}
return 0;
}