树相关 笔记
本文原在 2025-01-19 17:31 发布于本人洛谷博客。
一、树的直径
就是树上最长的一条链。
法一:两次 dfs
先随便挑一个点,dfs 找到离这个点最远的点,再从找到的这个点出发 dfs,找到离这个点最远的点,这两点之间的路径就是直径。
法二:dp
随便挑一个点往下 dp,找到从每个点 \(u\) 出发往子树内走到叶子的最长链 \(d_{1,u}\) 和次长链 \(d_{2,u}\),\(\max\{d_{1,u}+d_{2,u}\}\) 就是直径。
二、树的重心
就是找到一个点,使以他作为根时,最大的子树大小,比以任何其他点作为根时的最大子树大小都要小。
直接一次 dfs 就能找到。
三、Prüfer 序列
1. 定义
用一个长度为 \((n - 2)\),值域为 \([1,n]\) 的序列表示一棵树。
构建方法:每次找到编号最小的叶子节点 \(u\),记他的父亲为 \(fa\),将 \(fa\) 加入序列并删去 \(u\)。
2. 构造
显然可以 \(O(n)\) 构造,就直接从小到大遍历编号,这个编号是叶子节点就判断它父亲的编号是否比叶子节点还要小,是的话就接着删,否则继续遍历。
3. 性质
- 每个点在序列中出现的次数即为其度数减一。
因为每个点的所有 \(c\) 个儿子都会最终成为叶子结点,将这个点加入序列 \(c\) 次,而这个点的度数显然是 \(c+1\)(加上连向父亲的边)。
4. 重建树
由性质,可以从 Prüfer 序列知道每个点的度数,哪些是叶子节点。同样从小到大遍历编号,找到最小的叶子结点,将每个点父亲从前往后设为 Prüfer 序列的每个编号即可。
如果某个点被连接的次数等于他儿子的个数,那他也相当于一个“叶子结点”,往上连边。判断他的连接次数也是很好维护的。
5. 性质
- 一个有 \(n\) 个点的完全无向图有 \(n^{n-2}\) 个生成树。
一个树对应一种 Prüfer 序列的填法,Prüfer 序列 \((n-2)\) 个位置每个位置都有 \(n\) 种填法。
6. Caylay 公式
相当于规定了每个点在 Prüfer 序列中出现的次数。
为方便表述,令 \(a_i\gets d_i-1\)(题目中的 \(d_i\),原理即第 \(3\) 点提到的性质),令 \(m\gets n-2\)。
第一个点 \(m\) 个位置随便选 \(a_1\) 个组合地放,第二个点 \(m-a_1\) 个位置随便选 \(a_2\) 个组合地放,以此类推:
即
红色的全都消掉了,蓝色的因为 \((\sum_{i=1}^m a_i)=m\),所以值等于 \(1\)。
那么就是

浙公网安备 33010602011771号