【C++竞赛】note:广度优先搜索(BFS)

今天没有例题!


广度优先搜索(BFS)介绍

广度优先搜索(Breadth-First Search,简称BFS)是一种用于遍历或搜索树或图的算法。它从根节点(或任意节点)开始,逐层探索邻近节点,先访问离起点最近的节点。


基本思想

BFS的核心思想是"先广后深",即:

  1. 访问起始节点
  2. 依次访问起始节点的所有相邻节点
  3. 对这些相邻节点,再依次访问它们的未被访问过的相邻节点
  4. 重复上述过程,直到所有可达节点都被访问

算法实现

BFS通常使用队列(FIFO)数据结构来实现:

BFS(起始节点):
    1. 创建一个队列Q,并将起始节点放入Q
    2. 标记起始节点为已访问
    3. while Q不为空:
        a. 从Q中取出第一个节点v
        b. 访问v
        c. 将v的所有未被访问的相邻节点加入Q
        d. 标记这些相邻节点为已访问

特点

  • 完备性:如果解存在,BFS一定能找到(在无限图中如果解存在有限深度)
  • 最优性:对于无权图,BFS能找到最短路径
  • 空间复杂度:O(b^d),其中b是分支因子,d是解的深度
  • 时间复杂度:O(b^d)

应用场景

  1. 无权图的最短路径问题
  2. 社交网络中查找人与人之间的最短关系链
  3. 网络爬虫的网页抓取
  4. 迷宫求解
  5. 连通性检测
  6. 广播网络中的信息传播

与深度优先搜索(DFS)的比较

  • BFS使用队列,DFS使用栈(递归实现隐式使用调用栈)
  • BFS适合寻找最短路径,DFS适合寻找是否存在路径
  • BFS空间复杂度通常高于DFS
  • BFS在深度大的情况下可能不实用,而DFS可能在分支多的情况下不实用

BFS是许多更复杂算法的基础,如Dijkstra算法和Prim最小生成树算法都可以看作是BFS的变种。


广度优先搜索的示列代码

解题的通式1:

#include <bits/stdc++.h>
using namespace std;

signed main()
{
    queue<int> q;
    
    // ! 将队列初始状态入队
    q.push("初始状态");

    while(!q.empty)
    {
        // ! 取出队首元素
        State cur = q.front();
        // ! 队首出队
        q.pop();
        // ! 找到u所有可能性v
        for("枚举所有可能状态")
        {
            // ! 状态v是否合法,如未访问过,未在队列中
            if("状态合法")
            {
                // ! 状态v入队,同时可能要维护某些信息,记录路径
                q.push("新状态");
            }   
        }
    }
}

解题通式2:

#include <bits/stdc++.h>
using namespace std;

int n;
int dis[1000005];

void bdf(int s)
{
    for(枚举所有可能状态)
    {
        dis[当前状态] = -1;
    }
    queue<int>q;
    dis[初始状态] = 0;
    q.push(初始状态);
    while(!Q.empty)
    {
        state u=q.front();
        q.pop();
        if(当前状态是答案状态)记录答案
        for(枚举所有可能状态)
        {
            if(状态合法)
            {
                state v=当前状态u进行决策得到的新状态;
                if(v满足题目限制条件 && dis[状态v]==-1)
                {
                    q.push(v);
                    dis[状态v] = dis[u] + 1;
                }
            }
        }
    }
}

老师上课原装正版代码:
bfs:(模板)

//State 为结构体类型的名字 
#include<bits/stdc++.h>
using namespace std;
int n;
int dis[100006];
void dfs(){
	//dis 数组表示起始状态到每一个状态的最小步数
	for(枚举所有状态)dis[当前状态]=-1;//数组初始化 
	queue<State>Q;
	dis[初始状态]=0;
	Q.push(初始状态);
	if(当前状态u是答案状态)记录/处理答案; 
	while(!Q.enpty()){//当队列不为空,说明还没有处理完所有状态 
		State u=Q.front();
		Q.pop();
		for(枚举所有当前状态可以进行的决策/选择/行为){
			State v=当前状态u惊醒当前决策得到的新状态;
			if(当前状态v满足题目限制条件 && dis[v]==-1){
				Q.push(v);
				dis[v]=dis[u]+1;
			} 
		}
	} 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值