PrepStack · Markdown HTML

DFS 连通块与可达性

遍历与连通性 · HTML

数学 / 逻辑形态

给定图 G=(V,E) 与合法节点集合 A。对每个尚未访问的 v∈A 启动一次 DFS;一次搜索访问的节点恰组成 v 所在的连通分量。

识别信号

容易误判的相似信号

SignalWhy it is different
无权最短路DFS 首次到达不保证最少边数;改用 bfs-unweighted-shortest。
依赖顺序有向依赖的重点是入度或递归颜色,不是普通连通遍历。

核心不变量

节点一旦标记 visited,就已被归入当前搜索代表的分量,之后不会属于另一分量。

状态、转移与处理顺序

ItemDefinition
State当前节点 u、全局 visited,以及可选的分量聚合器(大小、和、边界等)。
Transition枚举 u 的邻居 v;若合法且未访问,则先标记,再递归或压栈。
Frontier / order递归调用栈或显式 LIFO 栈,保存已发现但尚未完全展开的节点。

Python 骨架

def components(graph):
    seen, groups = set(), []
    for start in graph:
        if start in seen:
            continue
        seen.add(start)
        stack, group = [start], []
        while stack:
            u = stack.pop()
            group.append(u)
            for v in graph[u]:
                if v not in seen:
                    seen.add(v)
                    stack.append(v)
        groups.append(group)
    return groups

正确性思路

  1. 可靠性:只有沿真实边从 start 可达的节点才会被压栈。
  2. 完备性:对任意可达节点取一条路径;沿路径归纳,每个前驱展开时都会发现后继。
  3. 不重不漏:发现时标记使节点至多入栈一次;外层循环为每个尚未归类节点启动新分量。

复杂度

TimeSpaceParameters
O(V+E)O(V)V 为节点数,E 为邻接表中的边记录总数。

边界条件

错误模式

PatternWhy it fails / fix
弹出后才标记同一节点可能被多个邻居重复压栈;通常发现时标记。
只搜一个起点只能得到一个分量;统计全图必须扫描所有节点。
边方向建错漏建无向图的反向边会把连通性误算成单向可达性。

选择与排除规则

相关模板

RelationTemplateBoundary
递归反转替代链表指针改线递归返回后重连,但需承担 O(n) 调用栈。
traversal-foundation树形 DPDFS 提供 parent 与 postorder 骨架。
动态连通替代并查集动态连通性边持续加入且要反复查询连通性。

原创微型例子

环节内容
Result得到 {p,q,r} 与 {s} 两个分量。
Setupp—q—r 相连,s 孤立。
Trace从 p 依次发现 q、r;外层跳过它们,再从 s 启动。

Recall prompts

我的补充