双向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;
}
posted on 2025-03-29 10:02  fish2012  阅读(33)  评论(0)    收藏  举报  来源