图论:BFS算法题模板

from collections import deque

def bfs_template(start):
    visited = set()          # 已访问集合(防重复/环检测)
    queue = deque([start])   # 初始化队列(可携带初始参数如步数)
    
    while queue:
        level_size = len(queue)  # 当前层节点数(用于层次遍历统计)
        for _ in range(level_size):  # 层次处理循环(非必须)
            current = queue.popleft()
            # 终止条件检测(根据问题灵活设置)
            if is_target(current):  
                return result
            # 生成相邻节点(核心拓展逻辑)
            for neighbor in get_neighbors(current):
                if neighbor not in visited:
                    visited.add(neighbor)
                    queue.append(neighbor)
    
    return default_result  # 无解情况

四大必改模块说明

1. 状态表示
# 示例1:二维坐标 (x, y)
current = (x, y)

# 示例2:字符串状态(如单词变换)
current = "hot"

# 示例3:复合状态(携带额外参数)
current = (x, y, steps, keys_held)

2.终止条件

def is_target(state):
    # 示例1:到达迷宫终点
    return state == (N-1, M-1)
    
    # 示例2:字符串变为目标词
    return state == "cog"
    
    # 示例3:收集所有钥匙(位运算校验)
    return state[2] == 0b1111

3.邻居生成

def get_neighbors(state):
    # 示例1:四方向移动
    dx = [-1, 1, 0, 0]
    dy = [0, 0, -1, 1]
    return [(state[0]+dx[i], state[1]+dy[i]) for i in range(4)]

    # 示例2:单词字符变换
    return [word[:i]+c+word[i+1:] for i in range(len(word)) for c in 'abcdefghijklmnopqrstuvwxyz']

    # 示例3:状态机转移(如自动机问题)
    return next_states_map[state]

4.状态去重

# 根据问题选择编码方式:
visited.add(state)                  # 原始对象(需可哈希)
visited.add((x, y))                 # 元组编码  
visited.add(",".join(map(str, pos))) # 字符串编码
visited.add(bitmask)                # 位压缩编码

注意要点:

  1. 队列初始化:起始状态必须合法
  2. 去重策略:状态编码决定空间复杂度
  3. 层次处理

    level_size 循环实现按层统计,层次遍历就像给每个探索点贴"第几步到达"的标签

  4. 剪枝优化:在入队前过滤无效状态
  5. 路径记录:可用字典保存前驱节点(如需要输出路径)

举例

二叉树层序遍历
def levelOrder(root):
    if not root: return []
    q = deque([root])
    res = []
    while q:
        level = []
        for _ in range(len(q)):
            node = q.popleft()
            level.append(node.val)
            if node.left: q.append(node.left)
            if node.right: q.append(node.right)
        res.append(level)
    return res
迷宫最短路径
def shortestPath(maze, start, destination):
    dirs = [(0,1),(0,-1),(1,0),(-1,0)]
    m, n = len(maze), len(maze[0])
    q = deque([(start[0], start[1], 0)])
    visited = set()
    
    while q:
        x, y, steps = q.popleft()
        if [x,y] == destination: return steps
        if (x,y) in visited: continue
        visited.add((x,y))
        
        for dx, dy in dirs:
            nx, ny = x+dx, y+dy
            if 0<=nx<m and 0<=ny<n and maze[nx][ny]==0:
                q.append((nx, ny, steps+1))
    
    return -1
字符串接龙

def judge(s1,s2):  #判断是否可以转移
    count=0
    for i in range(len(s1)):
        if s1[i]!=s2[i]:
            count+=1
    return count==1
        
n=int(input())
beginstr,endstr=map(str,input().split())
if beginstr==endstr:  
	print(0)
	exit()
strlist=[]        #所有节点,帮助判断neibor子节点
for i in range(n):
	strlist.append(input())

# use bfs
visit=[False for i in range(n)]  #visited访问标识
queue=[[beginstr,1]]               #deque初始化
while queue:
	str,step=queue.pop(0)  #没用层序遍历,而是用了step记录长度,如果要路径就是列表
	if judge(str,endstr):    #判断最终条件
		print(step+1)
		exit()       #退出
	for i in range(n):
		if visit[i]==False and judge(strlist[i],str): #判断条件,可转移且未访问
			visit[i]=True
			queue.append([strlist[i],step+1])    #入列并将step加1
print(0) #默认输出,遍历完了都没有istarget(),比如无法转换的输出

完全可达性
def is_reachable_all_nodes(n, edges, start):
    # 构建邻接表,输入edge->[1,2]即1到2有一条路径
    adj = [[] for _ in range(n)]
    for u, v in edges:
        adj[u].append(v)
    
    visited = set()
    queue = deque([start]) #初始化
    visited.add(start)  #已经访问列表
    
    while queue:  
        node = queue.popleft()
        # 邻居生成:遍历所有出边
        for neighbor in adj[node]:
            if neighbor not in visited:
                visited.add(neighbor)
                queue.append(neighbor)
    
    # 完全可达判定:已访问节点数等于总节点数
    return len(visited) == n

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值