树论杂题选做
题目来源 luogu.
1. [USACO19DEC] Milk Visits S
简明题意:树上的每个结点都是黑白两种颜色之一,每次询问一条链上是否有某种颜色。
思路:
一道简单的套路题……
两种颜色可以分开讨论,每次关注一种颜色即可。
加强一下这道题,改成询问一条链上某种颜色结点的个数。
dfs预处理出树上结点到根节点的路径上某种颜色结点的个数,不妨记为\(dep[u][color]\)。
于是答案就是\(dep[u][color]+dep[v][color]-dep[lca][color]-dep[father[lca]][color]\),做完了。
时间复杂度\(O(n\log n)\)。
2. 会议
简明题意:给定一棵边权为1的无根树,找出一个结点,使得其他结点到该结点的距离和最小,且编号最小。
思路:
你需要知道一个结论:树的重心到树上其他节点的距离和最小。
于是这道题就做完了(笑
当然更普适的做法是换根dp,这里不予讨论。
时间复杂度\(O(n)\)。
3. 【XR-3】核心城市
题意:
给定一棵边权为1的无根树,选取 \(k\) 个特殊结点,使:
- 这些点两两可不经过非特殊结点而相互到达。
- 非特殊结点到其最近的特殊结点的距离的最大值最小。求出这个最小值。
思路:
个人认为从反方向考虑更加简单一些。
显然有这样的思路:每次都将树的叶子结点删去,直至树中剩余结点数量为 \(k\)。
类似于拓扑排序,我们可以通过队列来模拟。
因为树的边权都为1,可以证明这样做的正确性。
还有一个问题:如何计算最终的答案?
可以这样想:特殊结点到这个点的距离,就是这个点到特殊结点的距离。(废话
于是我们可以对每个结点定义一个\(d[u]\),初始化为1。
每次删除叶子节点时,用它们的\(d\)值更新新的叶子结点的\(d\)值,
具体地,若有结点\(u\)为叶子结点,\(v\)为一个与它相邻的新的叶子结点,则有\(d[v]=d[u]+1\)。
最后队列里剩下的\(d\)值就是答案了。时间复杂度\(O(n)\)。
4. 仓鼠找sugar
简明题意:多次判断树上的两条链\((a,b)\)和\((c,d)\)是否有交点。
思路:
简便起见,记\(f\)为\(lca(a,b)\),记\(g\)为\(lca(c,d)\)。
然后就是暴力分类讨论。不妨设\(dep[f]\leqslant dep[g]\)。
- 若\(dep[f]=dep[g]\):显然只有\(f=g\)时两条链才能重合。
- 若\(dep[f]<dep[g]\):
这个时候两条链重合当且仅当\(a,b\)中有一点在\(g\)所在子树内。
这等价于\(lca(a,g)=g\)或\(lca(b,g)=g\)。
于是就做完了。
5. [AHOI2008] 紧急集合
简明题意:边权全部为1的无根树上有\(a,b,c\)三点(可重合),找到一个点\(p\)使得到这三个点的距离最小,并求出这个最小值。
思路:
注意到三个点中必然有至少两对点的LCA是相同的。显然集合点应取不重合的LCA处。
计算距离的方法同第一题,最终会发现都是 \(dep[a]+dep[b]+dep[c]-dep[lca1]-dep[lca2]-dep[lca3]\)。