BFS 广度优先搜索(Breadth-First-Search)
宽度优先搜索,BFS是用于图的查找算法(要求能用图表示出问题的关联性)。
BFS可用于解决2类问题:
1.从A出发是否存在到达B的路径;
2.从A出发到达B的最短路径;
整体思路其思路为从图上一个节点出发,访问先访问其直接相连的子节点,若子节点不符合,再问其子节点的子节点,按级别顺序(一层一层)依次访问,直到访问到目标节点
· 起始:将起点(源点,树的根节点)放入队列中
· 扩散:从队列中取出队头的结点,将它的相邻结点放入队列,不断重复这一步
· 终止:当队 列为空时,说明我们遍历了所有的结点,整个图都被搜索了一追
对于所有边长度相同的情况,比如地图的模型,bfs第一次遇到目标点,此时就一定是从根节点到目标节点最短的路径(因为每一次所有点都是向外扩张一步,你先遇到,那你就一定最短)。bfs先找到的一定是最短的。但是如果是加权边的话这样就会出问题了,bfs传回的是经过边数最少的解,但是因为加权了,这个解到根节点的距离不一定最短。比如1000+1000是只有两段,1+1+1+1有4段,由于bfs返回的经过边数最少的解,这里会返回总长度2000的那个解,显然不是距离最短的路径。此时我们就应该采用Dijkstra最短路算法解决加权路径的最短路了。
练习
cpp
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int N=110;
int g[N][N];
int d[N][N];
int n,m;
int dx[4]={0,0,-1,1};
int dy[4]={1,-1,0,0};
int bfs()
{
queue<int> qx,qy;
memset(d,-1,sizeof d);
d[0][0]=0;
qx.push(0);
qy.push(0);
while(!qx.empty())
{
int x=qx.front();qx.pop();
int y=qy.front();qy.pop();
for(int i=0;i<4;i++)
{
int nx=x+dx[i];
int ny=y+dy[i];
if(nx>=0&&nx<n&&ny>=0&&ny<m&&g[nx][ny]==0&&d[nx][ny]==-1)
{
d[nx][ny]=d[x][y]+1;
qx.push(nx);
qy.push(ny);
}
}
}
return d[n-1][m-1];
}
int main()
{
cin>>n>>m;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
cin>>g[i][j];
}
}
cout<<bfs();
return 0;
}
多源bfs
染色问题
P1059 [NOIP 2006 普及组] 明明的随机数 - 洛谷
有限制的bfs
P2895 [USACO08FEB] Meteor Shower S - 洛谷
比较难的几个
P2658 汽车拉力比赛 - 洛谷(与二分相结合)
P1126 [CERC1996] 机器人搬重物 - 洛谷(增加了一个方向)
双端队列bfs
P4667 [BalticOI 2011] Switch the Lamp On (Day1) - 洛谷
双向队列(一维与二维的转换而且变换的是0的位置)---只要是有终点和起点的都可以