有序前沿与路径 · HTML
数学 / 逻辑形态
relax u→v,w∈{0,1};改善后 w=0 用 appendleft,w=1 用 append,使 deque 中待处理标签保持至多相差一层。
识别信号
- 动作分成免费与花费一次两类。
- 边权严格属于 {0,1}。
- 目标最小化付费动作数量而非总动作数。
- Dijkstra 可做但二叉堆显得过重。
容易误判的相似信号
| Signal | Why it is different |
|---|
| 所有动作等价 | 若全为 1,普通 BFS 更简单。 |
| 权值 0 与任意正数 | append/appendleft 只能编码两个相邻优先级;一般非负权用 Dijkstra。 |
核心不变量
deque 中从左到右的候选距离非递减;0 边不改变层级,1 边进入下一层。
状态、转移与处理顺序
| Item | Definition |
|---|
| State | dist、deque 中的节点或 (distance,node),以及 0/1 边生成器。 |
| Transition | 若 nd=dist[u]+w 改善 v,则更新;w=0 放左端,w=1 放右端。 |
| Frontier / order | 双端队列充当只有两个相对优先级的桶式优先队列。 |
Python 骨架
from collections import deque
def zero_one_bfs(graph, start):
inf = float('inf')
dist = {u: inf for u in graph}
dist[start] = 0
dq = deque([start])
while dq:
u = dq.popleft()
for v, w in graph[u]:
if w not in (0, 1):
raise ValueError('weight must be 0 or 1')
nd = dist[u] + w
if nd < dist.get(v, inf):
dist[v] = nd
if w == 0:
dq.appendleft(v)
else:
dq.append(v)
return dist
正确性思路
- 从左端弹出的候选具有最小待处理距离:免费边留在当前距离,付费边只进入下一距离。
- 每次 relaxation 都产生一条真实路径上界,且更优标签被放到正确优先级。
- 这等价于对 0/1 权 Dijkstra 的堆顺序做两桶压缩,因此最终 dist 最优。
复杂度
| Time | Space | Parameters |
|---|
| O(V+E) | O(V) | 每次成功改善导致 O(1) deque 操作;标准 0/1 图中总扫描与边规模线性同阶。 |
边界条件
- 全零边时所有同分量距离为 0。
- 全一边时退化为普通 BFS。
- 零权环不能依靠 visited 过早封死改善。
- 邻接表中的非法权值应断言或改用 Dijkstra。
错误模式
| Pattern | Why it fails / fix |
|---|
| 0 边也 append | 免费候选被放在更贵候选后面,破坏有序前沿。 |
| 只用 visited 不用 dist | 节点可能先由成本 1 路径发现,后由成本 0 前缀改善。 |
| 把边数当成本 | 答案统计的是 1 权边数量,不是动作总数。 |
选择与排除规则
- 权值集合恰为 {0,1}:优先 0-1 BFS。
- 只有 {0,c} 且 c 固定正数:缩放后同样适用。
- 权值出现第三种非等价值:回到 Dijkstra。
相关模板
原创微型例子
| 环节 | 内容 |
|---|
| Result | s 到 a 的最低成本是 0,而非首次发现的 1。 |
| Setup | s→a 花 1,s→b 花 0,b→a 花 0。 |
| Trace | a:1 先在右端,b:0 放左端;弹 b 后把 a 改善为 0 并放左端。 |
Recall prompts
我的补充