双向BFS算法讲解及例题
算法思想
双向BFS,那么根据名字就可以只到大概的意思,从两个方向进行BFS。
我们从问题的起点与终点同时BFS,起点遍历一层,终点也遍历一层,最终相遇时停止。
如果题目是求最小的操作次数,那么这就是最终的答案。
这样,就把问题分成了两半,减少的不必要的搜索。
算法优势

上面这张图中,黄色的部分表示普通的单向BFS查询到的范围,而紫色的范围表示的是双向BFS查询的范围。
可以明显看出,双向BFS的查询范围要比单向BFS小。
算法限制
当然了,双向BFS也是有限制条件的,首先必须得先知道终点,不然根本没法双向BFS。
其次就是点
x
x
x到点
y
y
y的权值要和点
y
y
y到点
x
x
x的权值是一样的,不然从终点往后搜答案就不对。
例题
Word Ladder
考虑用搜索。
我们可以暴力对每个字符串的变换的每种可能进行查询,用map标记一下是不是在题目要求里面,然后从终点也进行BFS遍历两次相汇的地方就是答案,答案就是把两端遍历的长度加起来,注意要减一,因为相遇的那个点两端都遍历到了,产生了重复。
例题代码
写的像坨 ∗ * ∗一样。
#include<bits/stdc++.h>
using namespace std;
string s,t;
string R;
unordered_map<string,bool>mp;
unordered_map<string,bool>visp;
unordered_map<string,bool>visq;
unordered_map<string,int>disp;
unordered_map<string,int>disq;
struct node{
string s;
int x;
};
void bfs(){
queue<node>q;
queue<node>p;
q.push(node{s,1});
p.push(node{t,1});
disq[s]=1;
disp[t]=1;
visq[s]=1;
visp[t]=1;
while(!q.empty()&&!p.empty()){
node Q=q.front();
node P=p.front();
q.pop();
p.pop();
if(Q.s==P.s){
cout<<Q.x+P.x-1;
exit(0);
}
if(visp[Q.s]){
cout<<Q.x+disp[Q.s]-1;
exit(0);
}
if(visq[P.s]){
cout<<P.x+disq[P.s]-1;
exit(0);
}
for(int i=0;i<Q.s.size();i++){
for(char c='a';c<='z';c++){
string l=Q.s;
l[i]=c;
if(!mp[l]||visq[l])continue;
if(disq[l]==0)disq[l]=1e9;
disq[l]=min(disq[l],Q.x+1);
q.push(node{l,Q.x+1});
visq[l]=1;
}
}
for(int i=0;i<P.s.size();i++){
for(char c='a';c<='z';c++){
string l=P.s;
l[i]=c;
if(!mp[l]||visp[l])continue;
if(disp[l]==0)disp[l]=1e9;
disp[l]=min(disp[l],P.x+1);
p.push(node{l,P.x+1});
visp[l]=1;
}
}
}
}
signed main(){
ios::sync_with_stdio(0);
cin>>s>>t;
while(cin>>R)mp[R]=1;
bfs();
cout<<-1;
}
浙公网安备 33010602011771号