双向 BFS
概念讲解
什么是双向 BFS?
从起点和终点同时 BFS,当两个搜索相遇时找到最短路径。
优势
将搜索空间从 降低到 。
实现
123456789101112131415161718int bidirectionalBFS(int start, int end) {
queue<int> q1, q2;
unordered_map<int,int> dist1, dist2;
q1.push(start); dist1[start] = 0;
q2.push(end); dist2[end] = 0;
while (!q1.empty() && !q2.empty()) {
// 从起点扩展
int result = expand(q1, dist1, dist2);
if (result != -1) return result;
// 从终点扩展
result = expand(q2, dist2, dist1);
if (result != -1) return result;
}
return -1;
}考点分析
初赛考查方式
- 程序阅读: 双向 BFS
- 编程题: 最短路径
常见考点
- 双向 BFS 原理
- 相遇判定
- 效率分析
练习题
- 双向 BFS 的优势?
查看答案
双向 BFS 的优势:
将搜索空间从 降低到 。
其中 b 是分支因子,d 是搜索深度。
例如:b=10, d=6
- 普通 BFS:
- 双向 BFS:
- 什么时候用双向 BFS?
查看答案
双向 BFS 适用于:
- 知道起点和终点
- 搜索空间很大
- 分支因子较大
例如:八数码问题、单词接龙等。
- 如何判断相遇?
查看答案
判断相遇的方法:
在扩展一个方向时,检查当前节点是否已被另一个方向访问过。
12345678910111213141516int expand(queue<int>& q, unordered_map<int,int>& dist1, unordered_map<int,int>& dist2) {
int u = q.front();
q.pop();
for (int v : getNeighbors(u)) {
if (dist2.count(v)) {
return dist1[u] + 1 + dist2[v];
}
if (!dist1.count(v)) {
dist1[v] = dist1[u] + 1;
q.push(v);
}
}
return -1;
}易错点
⚠️ 注意:
- 要同时扩展两端
- 遇到已访问节点即相遇
- 适用于知道终点的情况
- 效率提升明显