笔记-dfs在图和树中的一次遍历的区别

这是函数的定义部分,dfs 函数接受三个参数:

def dfs(x: int, fa: int, d: int) -> int
    if d > k:
        return 0
    cnt = 1
    for y in g[x]:
        if y != fa:
            cnt += dfs(y, x, d + 1)
    return cnt
  • x (int 类型):表示当前正在访问的节点的编号。
  • fa (int 类型):表示节点 x 的父节点的编号。这是为了在遍历过程中避免沿着已经访问过的路径返回,防止形成死循环。
  • d (int 类型):表示从根节点到当前节点 x 的深度(路径长度)。

一、树结构中避免访问父节点的原理

在树结构中,任意两个节点之间只有一条路径,每个节点(除了根节点)都有唯一的父节点。代码中的 fa 参数记录了当前节点 x 的父节点,通过 if y != fa 判断,可以确保不会从当前节点回到父节点,从而避免循环。

例如,在调用 dfs(x, fa, d) 时:

  • x 是当前节点
  • fa 是 x 的父节点
  • 遍历 x 的邻接节点 y 时,如果 y 等于 fa,说明这个邻接节点是父节点,应该跳过

二、图结构中这种方法的局限性

在图结构中,节点之间可能存在多条路径和环路,仅仅记录父节点是不够的。例如:

  • 如果图中存在环,即使跳过父节点,仍然可能通过其他路径回到已经访问过的节点
  • 对于无向图中的边 (u, v),在遍历 u 的邻接节点时会访问 v,而遍历 v 的邻接节点时又会访问 u,导致重复遍历

三、图结构中的正确处理方法

在图中进行 DFS 时,通常需要使用一个全局的 visited 数组或集合来记录已经访问过的节点,避免重复访问。以下是修改后的代码示例:

visited = set()  # 全局集合,记录已访问的节点

def dfs(x: int, d: int) -> int:
    if d > k:
        return 0
    if x in visited:  # 如果节点已被访问,直接返回0
        return 0
    visited.add(x)  # 标记当前节点为已访问
    cnt = 1
    for y in g[x]:
        cnt += dfs(y, d + 1)  # 递归访问邻接节点,不再需要fa参数
    return cnt

四、总结

  1. 树结构:由于其无环特性,使用 fa 参数可以有效避免重复访问父节点
  2. 图结构:必须使用 visited 集合来记录已访问节点,否则会导致:
    • 无限循环(如果图中存在环)
    • 重复计算(即使图中没有环
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值