跳转至

BISHI97 旺仔哥哥走迷宫

中等通过率 47.23%python3样例通过牛客 AC

牛客原题  源码

讲解章节BFS 广度优先搜索

一句话

无向图,只能经过安全房间,问 1 能否到 n。

解题思路

这题考什么

带点权限制的连通性判定。把「有陷阱的房间」直接当作不存在的点删掉, 剩下的图上做一次 BFS / DFS,看 n 是否可达。 BFS 的框架见 61-BFS广度优先搜索

数据规模与复杂度

n, m <= 1e5。建邻接表 O(n + m),一次遍历 O(n + m)。

Python 的坑

  1. 用 BFS + collections.deque,天然迭代,不会有递归深度问题 (这张图可能是一条 1e5 长的链,递归 DFS 必然 RecursionError); deque.popleft 是 O(1),绝不能用 list.pop(0);
  2. 邻接表用定长 [[] for _ in range(n+1)],不要 defaultdict(list)—— 1e5 规模下哈希开销明显;
  3. 建表时顺手过滤掉陷阱点:只有两端都安全的边才加入, 这样 BFS 内层循环就不用再判断 t[v],常数更小。

坑在哪

  1. 起点 1 自己可能就有陷阱,此时直接 No(BFS 都不该开始); 终点 n 有陷阱同理;
  2. n = 1 时起点即终点,只要 1 号房安全就是 Yes;
  3. 可能有重边、自环,对连通性判定无影响,不必去重。

参考实现

solutions/BISHI97.py
import sys
from collections import deque


def main() -> None:
    data = sys.stdin.buffer.read().split()
    n, m = int(data[0]), int(data[1])
    trap = data[2:2 + n]                    # b'0' / b'1'
    ONE = b'1'                              # 直接比较 bytes,省掉 n 次 int() 转换

    if trap[0] == ONE or trap[n - 1] == ONE:   # 起点或终点本身有陷阱
        sys.stdout.write("No\n")
        return

    # ---- 建邻接表,同时把与陷阱点相连的边全部剔除 ----
    adj = [[] for _ in range(n + 1)]
    p = 2 + n                               # 前 2 + n 个 token 是 n、m 与陷阱数组
    for _ in range(m):
        a = int(data[p]); b = int(data[p + 1]); p += 2
        if trap[a - 1] == ONE or trap[b - 1] == ONE:
            continue                        # 建表时就把陷阱点相关的边扔掉
        adj[a].append(b)
        adj[b].append(a)

    # ---- 从 1 号房间 BFS,能走到的都是安全可达的房间 ----
    vis = bytearray(n + 1)
    vis[1] = 1                              # 入队时就打标记,避免同一点重复入队
    q = deque([1])
    while q:
        u = q.popleft()
        if u == n:                          # 出队时判终点,n == 1 时第一轮即命中
            sys.stdout.write("Yes\n")
            return
        for v in adj[u]:
            if not vis[v]:                  # 邻居必定安全(不安全的边建表时已丢弃)
                vis[v] = 1
                q.append(v)
    sys.stdout.write("No\n")        # n == 1 时上面第一轮就命中 u == n 返回 Yes 了


main()
[:octicons-arrow-left-16: BISHI96](BISHI96.md) [BISHI98 :octicons-arrow-right-16:](BISHI98.md)