搜索-广度优先搜索(BFS)

Posted ACM算法

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了搜索-广度优先搜索(BFS)相关的知识,希望对你有一定的参考价值。

广度优先搜索(BFS)

在图论的基本介绍中简单的讲了如何将图存进计算机,而BFS(广度优先搜素)就是对存进去的图进行搜索,需要强调的是,BFS不仅能用于对图的搜索。

BFS思想

假设我们从点u开始搜索,需要找到点a_1,已知与点u有关系的点为v_1,v_2,与点v_1有关系的点为w_1,w_2,与点v_2有关系的点为a_1,a_2,我们如何通过这些关系找点a_1?你是否这样想过,通过点u找到v_1,v_2(很明显它们不是a_1),然后通过v_1找到w_1,w_2(它们也不是a_1),之后通过v_2找到a_1,a_2 (a_1就是我们要找的点)。如果你这样想过,那恭喜你理解理解了BFS。

BFS的思想是从已知的一个或一些点(称这些点的集合为A)开始对图进行搜索,先搜索A,再搜索与集合A有关系的点(称这些点的集合为B),然后搜索与集合B有关系的点,.... 最后搜索完整个图,很明显是一个循环的过程。通过这种方式搜索,如果在没有没有搜索完图时就找到结果,那么我们就可以跳出循环。在这里我们还需要一种数据结构,需要先找到的点先解决的数据结构,好像队列可以满足这种数据结构,没错就是队列。如此一来我们就可以去解决实际问题了。

模板

void BFS(){ 初始化一些数据; 初始化队列; 将开始的点入队; while(队列非空) { 1.取出第一个点x; 2.对x进行操作(找到结果,可以选择跳出循环);  3.将与x有关系的点存进队列; 4.删除点x;  } } //其中2,3,4步骤不分先后。


例题

链接http://acm.hdu.edu.cn/showproblem.php?pid=2544

在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt。但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗?

输入

输入包括多组数据。每组数据第一行是两个整数N、M(N<=100,M<=10000),N表示成都的大街上有几个路口,标号为1的路口是商店所在地,标号为N的路口是赛场所在地,M则表示在成都有几条路。N=M=0表示输入结束。接下来M行,每行包括3个整数A,B,C(1<=A,B<=N,1<=C<=1000),表示在路口A与路口B之间有一条路,我们的工作人员需要C分钟的时间走过这条路。输入保证至少存在1条商店到赛场的路线。

输出

对于每组输入,输出一行,表示工作人员从商店走到赛场的最短时间

样例输入

2 1
1 2 3
3 3
1 2 5
2 3 5
3 1 2
0 0

样例输出

3
2

例题分析

题目中要求多组输入输出,这里我们假设数据只有一组。其他的先不管,我们先把图存到计算机再说,代码如下(用vector数组存图):

vector< pair<int,int> > ve[110];//N最大只有100,所以用110完全可以表示int main(){ int n,m,u,v,w;//u,v,w分别为题中的A,B,C cin>>n>>m; for(int i=1;i<=m;i++){ cin>>u>>v>>w;//获取点与点与点之间的关系 ve[u].push_back(make_pair(v,w));//存图 ve[v].push_back(make_pair(u,w));//本题中是无向图 }}

很明显点与点之间的关系(边)是时间,搜索是从点1开始。我们遇到的问题是如何记录点到点之间所需要的时间,假设点1到点1的距离是0,到其他点的距离是无限大,我们从点1开始搜索与点1有关系(记为集合A)的点,这样我们就可以更新点1到集合A中每一个点的距离,然后通过集合A再搜索与这些点有关系的其他点,再更新点1到其他点的时间,一直更新到整个图结束,我们就找到点1到其他点的最短距离(其他点当然包括点n了)。其中点1到其他点的距离要用一个长度为n的数组储存,十六进制0x3f3f3f3fda的十进制为1061109567,可以用它来表示无限大。当然你可能还有很多疑问,不着急我们先看代码,代码如下:

int arr[110];//记录时间大小的数组 void BFS(int st)//st表示从那个点开始搜索,本题中st=1. { memset(arr,0x3f,sizeof(arr));//将数组arr中的每一个值设为0x3f3f3f3f  int u,v,w;//定义int变量u,v,w  arr[st]=0;//表示从点st到点st的时间为0  queue<int> qu;//建立队列  while(!qu.empty()) qu.pop();//如果队列部位空,则清空队列  qu.push(s);//将st入队  while(!qu.empty()) { u=qu.front();//取出第一个点  qu.pop();//取出后删除  for(int i=0;i<ve[u].size();i++)//遍历与点u有关系的所有点 { v=ve[u][i].first;//这个是另一个点  w=uv[u][i].second;//这个是两点之间的时间  if(arr[v]>arr[u]+w)//如果从st到v的距离大于从st到u再到v的距离就更新arr[v]  { arr[v]=arr[u]+w;//更新arr[v];  qu.push(v);//更新arr[v],说明从st到v再到其他点的值都要更新,所以添加v进入队列  } } }}

请仔细读上面的代码,有疑问的地方可以结合代码想一想,如果想不明白也没关系,这个题目其实是图论中的最短路问题,后面会有详细的讲解。作者选择这个题目的原因是最短路是最容易体现BFS与图的关系,当然为了表达作者的歉意,再次奉上作者的ac代码,存图采用的是链式前向星,代码有些个人习惯请不要建议:

#include<bits/stdc++.h>using namespace std;const int MI=1e5+10; struct uvw{ int u,v,w,next;};uvw uv[MI<<1];int head[MI];int arr[MI];void add(int u,int v,int w,int i){ uv[i].u=u;uv[i].v=v;uv[i].w=w; uv[i].next=head[u];head[u]=i;}void BFS(int s) { memset(arr,0x3f,sizeof(arr));  int u,v,w;  arr[s]=0;  queue<int> qu;  while(!qu.empty()) qu.pop();  qu.push(s);  while(!qu.empty()) { u=qu.front();  qu.pop();  for(int i=;ii=uv[i].next){ v=uv[i];  w=uv[i].w;  if(arr[v]>arr[u]+w) { arr[v]=arr[u]+w;  qu.push(v);  } } }}int main(){ int n,m,s,u,v,w; while(1){ scanf("%d%d",&n,&m);  if(n==0) break; memset(head,0,sizeof(head)); memset(uv,0,sizeof(uv)); for(int a=1,i=1;a<=m;a++) { scanf("%d%d%d",&u,&v,&w); add(u,v,w,i++); add(v,u,w,i++);  } BFS(1); printf("%d\n",arr[n]); }}


关键字

BFS广度优先搜索宽度优先搜索


以上是关于搜索-广度优先搜索(BFS)的主要内容,如果未能解决你的问题,请参考以下文章

BFS(广度优先搜索)邻接矩阵C ++

DFS-深度优先搜索与BFS-广度优先搜索

广度优先搜索(BFS)的一个(重要!)细节。

搜索-广度优先搜索(BFS)

深度优先搜索DFS和广度优先搜索BFS

Python算法-深度优先搜索&广度优先搜索(DFS&BFS)