思路详解
问题分析
我们需要计算树中从根节点出发能够到达的所有节点的路径总数. 这里的路径指的是从根节点向下延伸的简单路径 (不包含回头路).
错误思路分析
最初的朴素想法是从底层向上逐层计算每个节点对上层节点的贡献. 具体来说:
- 每个节点自身贡献1条路径 (只包含自己)
- 每个节点会向其所有非父节点的上层节点贡献其路径数
但这种做法需要对每个节点向上遍历所有祖先节点, 时间复杂度为$O (n²)$ , 对于$n=3×10⁵$的数据规模显然不可行
正确思路优化
采用动态规划的思想, 结合树的分层处理:
分层处理:首先将树按层次划分, 根节点在第0层, 其子节点在第1层, 以此类推.
路径计数规则:
- 每个节点至少有1条路径 (只包含自己)
- 每个节点会向其上层节点贡献其路径数 (因为上层节点可以通过子节点到达这些路径)
- 但父节点不能通过子节点到达子节点本身 (即不能直接使用子节点的路径数)
关键优化:
- 从底层向上处理, 维护一个”上一层总和”变量
- 对于当前层的每个节点:
- 首先加上上一层所有节点的路径总和 (因为这些节点都可以被当前节点的父节点到达)
- 然后从父节点的计数中减去当前节点的计数 (消除父节点不能到达当前节点的部分)
状态转移方程:
- 设$dp[u]$表示以$u$为根的子树中从根到$u$的路径数
- $dp[u] += 1 + Σdp[v] - Σdp[w]$ ($v$是$u$的下层节点, $w$是$u$的子节点)
复杂度分析
- 时间复杂度:$O (n)$
- 分层处理需要 $O (n)$ 时间
- 自底向上处理每层节点也是 $O (n)$
- 空间复杂度:$O (n)$
- 需要存储树的结构和每层节点信息
完整代码
1 | for _ in range(int(input())): |
我很可爱,请给我钱
- 本文链接: https://www.zh314.xyz/2025/03/26/CF2070D-D-Tree-Jumps-题解/
- 版权声明: 本博客所有文章除特别声明外,均默认采用 CC BY-NC-SA 4.0 许可协议。