树上问题
树可以理解为一种特殊的图:连通且无环。很多树题都离不开 DFS,因为树天然适合“从子树收集信息”。
------
1. 树的遍历
- 常见方式:先序、中序、后序、层序。
- 作用:访问树上所有结点,为后续统计高度、子树大小等打基础。
- 先序:先访问自己,再访问孩子
- 后序:先访问孩子,再访问自己
- 层序:一层一层访问(BFS)
- 题目说:“请输出遍历序列”
- 题目需要“遍历所有点”做统计(子树大小、深度、父子关系等)
- 题目是二叉树,问先序/中序/后序互相转化
- 树上很多统计都在 后序 做:因为后序能保证“孩子信息算完,父亲再算”
- 层序(BFS)适合处理:按层的距离、最短路、层数统计
类别定义
树的遍历就是:把树上每个结点都访问一遍,并且访问的顺序不同,会形成不同的遍历方式。
鉴别方法
思路技巧
核心伪代码(树 DFS 遍历)
void dfs(int u, int fa){
// 先序:进入 u 的这一刻(想要先序输出就在这里输出)
// visit(u);
for(int v: adj[u]){
if(v == fa) continue; // 防止走回父亲
dfs(v, u);
}
// 后序:离开 u 的这一刻(想要后序统计就在这里做)
// visit(u);
}核心伪代码(层序遍历 BFS)
queue<int> q;
q.push(root);
fa[root] = 0;
dep[root] = 0;
while(!q.empty()){
int u = q.front(); q.pop();
// visit(u);
for(int v: adj[u]){
if(v == fa[u]) continue;
fa[v] = u;
dep[v] = dep[u] + 1;
q.push(v);
}
}------
2. 树的直径
类别定义
树的直径就是“树上最远的两点”之间的距离。
鉴别方法
思路技巧(两次搜索)
关键结论:
从任意点出发找到的最远点 $A$,一定是某条直径的端点之一。
再从 $A$ 出发找到最远点 $B$,$A\leftrightarrow B$ 的距离就是直径长度。
------
3. 树上 DP
类别定义
树上 DP 的典型形式:选一个根,把树变成“父子结构”,然后:
鉴别方法
思路技巧
树上 DP 的写法几乎固定:
1. 选根(通常 1)
2.
dfs(u, fa)3. 先递归所有孩子
v4. 再把孩子的 dp 合并到
u核心伪代码(子树大小/子树和)
void dfs(int u,int fa){
sz[u]=1; // 子树至少包含自己
sum[u]=a[u]; // 子树权值和
for(int v:adj[u]){
if(v==fa) continue;
dfs(v,u);
sz[u]+=sz[v]; // 合并子树大小
sum[u]+=sum[v]; // 合并子树权值和
}
}核心伪代码
void dfs(int u,int fa){
// dp0[u]:u 不选的最优值
// dp1[u]:u 选的最优值
dp0[u]=0;
dp1[u]=w[u];
for(int v:adj[u]){
if(v==fa) continue;
dfs(v,u);
dp1[u] += dp0[v]; // u 选,则孩子不能选
dp0[u] += max(dp0[v], dp1[v]); // u 不选,孩子选不选都行
}
}------
4. 换根 DP
类别定义
换根 DP 就是:你想求“每个点当根时”的答案。
如果暴力做:每个点做一次 DFS,复杂度 $O(n^2)$,会超时。
换根 DP 的目标是:用两次 DFS 在 $O(n)$ 或 $O(n\log n)$ 算出所有点答案。
鉴别方法
思路技巧(两遍 DFS)
1. 第一遍 DFS(自底向上):算“子树内信息”
2. 第二遍 DFS(自顶向下):把“父亲那边的信息”传给孩子,得到全局答案
常见例子:每个点到所有点距离和
sz[u] 和 distSum[root]核心伪代码
void dfs1(int u,int fa){
// 先算子树信息
for(int v:adj[u]){
if(v==fa) continue;
dfs1(v,u);
// merge v -> u
}
}
void dfs2(int u,int fa){
// 把父亲方向的信息“下发”给孩子
for(int v:adj[u]){
if(v==fa) continue;
// push u -> v(根据题目写换根转移)
dfs2(v,u);
}
}【前置知识点】
1、最近公共祖先
【思维导图】

【题目知识点分类】
01
「NOI2011」道路修建
普及/提高-
--
练习
02
树的直径
普及/提高-
--
练习
03
STA-Station
普及+/提高
--
练习
04
Welcome24ever 和集会
普及+/提高
--
练习
05
Welcome24ever 和水坑
普及+/提高
--
练习
06
Welcome24ever 和神树
普及/提高-
--
练习
07
遍历问题
普及/提高-
--
练习
08
让我们异或吧
普及/提高-
--
练习
09
[GESP202406 六级] 二叉树
普及/提高-
--
练习
10
有线电视网
普及+/提高
--
练习
11
【树形动态规划】没有上司的舞会
普及/提高-
--
练习
12
Welcome24ever 和上帝
普及/提高-
--
练习
13
左孩子右兄弟
普及/提高-
--
练习
14
直径
普及+/提高
--
练习
15
最大颜色子树
普及+/提高
--
练习
16
Welcome24ever 和田地
普及+/提高
--
练习
17
保安站岗
普及+/提高
--
练习
18
Welcome24ever 和油漆
普及+/提高
--
练习
19
Welcome24ever 和电路板
普及+/提高
--
练习
20
Welcome24ever 和公园
提高+/省选-
--
练习