Loading

NOIP/CSP 树论题目口胡

我们假设你已经熟练掌握了树上的各项基础技术. 下面来做一下题吧!

1. [NOIP2007 提高组] 树网的核

简明题意:
给定一棵有 \(n\) 个结点的带权无根树, 在其直径上找到一段长度不大于 \(s\) 的链 (称为核, 可退化为一个点), 使得树上的其他结点到该路径距离的最大值 (称为偏心距) 最小.

我们发现原题里数据范围是 \(n\leqslant 300\), 但实际上我们可以做到 \(O(n)\).
大体思路就是, 我们随便找一条直径 \(D\), 然后在直径上尺取.
具体地, 记直径的端点分别为 \(l\), \(r\), 选取的核 \(C\) 两端分别为\(x\), \(y\).
接下来我们计算偏心距 \(E\). 为了方便表示, 记 \(d_u\) 为从 \(u\) 到它不经过直径能到达的最远点的距离.
容易发现, 有 \(E=\max\{\max_{u\in C}\{d_u\},dis(l,x),dis(y,r)\}\).
(注意直径是最长的链, 所以 \(x\) 所能到达的最远点是 \(l\), \(y\) 所能到达的最远点是 \(r\))
讲道理现在就已经能用尺取做了.
但是注意到, 对于链 \((l,x)\) 上任意一点, 其 \(d\) 值不会大于 \(dis(l,x)\). (\((y,r)\) 的情况同理)
则原式化简为 \(E=\max\{\max_{u\in D}\{d_u\},dis(l,x),dis(y,r)\}\).
此时 \(\max_{u\in D}\{d_u\}\) 这一项可以预处理出来, 不用在尺取中维护了.
最终我们就以 \(O(n)\) 的时间复杂度解决了这道题.

2. [NOIP2018 提高组] 赛道修建

简明题意:
给定一棵有 \(n\) 个结点的带权无根树, 现在要用 \(m\) 条路径来覆盖一些边, 且一条边不能被覆盖两次. 求长度最小的路径长度的最大值.

最小值最大, 不难想到要二分这个最小值. 然后就发现不好做了.
考虑部分分. 出题人非常良心, 给了我们一些提示.

  • \(m=1\). 显然取直径.
  • 链. 这就很典了, 贪心选择即可.

上面的部分分非常基础, 但也高达 40 分了(
进入正题.

  • 菊花图.
    注意每次只会取一条或两条边, 我们设当前二分的值为 \(mid\), 对大于等于 \(mid\) 和小于 \(mid\) 的边分开考虑.
    小于 \(mid\) 的边尽量配对, 这个双指针就能做. 余下的边和大于等于 \(mid\) 的边配对.
    如果还有小于 \(mid\) 的边说明不成立, 如果还有大于等于 \(mid\) 的边两两配对即可.

  • 每个点的度数 \(\leqslant3\).
    这个部分分就非常接近正解了. 首先我们随便钦定一个点作为根.
    为方便描述, 我们称一条链 \((u,v)\) 是直链当且仅当 \(u\)\(v\) 的祖先或 \(v\)\(u\) 的祖先.
    然后我们记 \(l_u\) 为使得答案最优的从 \(u\) 开始向下的直链长度. (有点抽象)
    我们考虑将一条链在端点的 LCA 处拆成两条直链. 这样我们只需要先统计直链, 然后两两合并即可.
    因为每个点的度数不超过 \(3\), 所以当前点最多有两个儿子. 分类讨论:

    • 并没有儿子: 显然 \(l_u=0\).
    • 只有一个儿子 \(v\):
      • \(l_v\geqslant mid\): 题目并没有说两条链不能占用相同顶点, 于是我们直接令 \(l_u=dis(u,v)\).
      • 否则令 \(l_u=l_v+dis(u,v)\), 若 \(l_u\geqslant mid\) 则计入答案, 否则不计.
    • 有两个儿子:
      • 如果有儿子满足 \(l_v\geqslant mid\), 那我们可以无视下面的直链, 而用 \(dis(u,v)\) 代替 \(l_v\) 参与 \(l_u\) 的计算.
      • 如果有儿子满足 \(l_v+dis(u,v)\geqslant mid\), 我们将这条链计入答案, 然后无视它.
      • 如果只有一个儿子 满足 \(l_v+dis(u,v)<mid\), 那我们令 \(l_u=l_v+dis(u,v)\).
      • 如果两个儿子都有 \(l_v+dis(u,v)<mid\), 那我们先尝试将两条链合并.
        • 如果两条链合并长度 \(\geqslant mid\), 那么将这条合并出的链计入答案, 并且令 \(l_u=0\).
        • 否则选 \(l_v+dis(u,v)\) 大的作为 \(l_u\).

部分分终于说完了. 正解就是将菊花图和度数 \(\leqslant3\) 的方法合起来.
我们考虑度数大于 \(3\) 的时候怎么合并.
显然对于加上 \(dis(u,v)\) 链长还小于 \(mid\) 的直链使用双指针进行合并就行. 在余下的直链中取一条最大的作为 \(l_u\).

然后就做完了(

3. [NOIP2015 提高组] 运输计划

简明题意: 给一棵 \(n\) 个点的带权无根树和 \(m\) 条链, 现在要将树上的一条边的权值改为 \(0\), 要求使修改后链的长度的最大值最小.

首先枚举改哪条边是没有出路的! 树剖/LCT \(O(nm\log^2n)/O(nm\log n)\) 就很难再优化了.
考虑二分答案, 所以说应该怎么判定?
记当前二分到的答案为 \(mid\).
首先我们找出来所有长度超过 \(mid\) 的链. 链的长度可以随手预处理掉.
然后我们只需要找出来这些链的交, 这个可以用树上差分维护.
最后在交出的链上枚举改哪条边的权值即可.

4. [NOIP2012 提高组] 疫情控制

题意:
给定一棵 \(n\) 个点的带权有根树, 树根为 \(1\).
现在一些点上有棋子, 共有 \(m\) 枚棋子, 且一个点上可以有多枚棋子.
现在要移动棋子, 使根到任意一个叶子的路径上都有至少一枚棋子. 注意棋子最终不能放到根上.
求移动距离最长的棋子经过的路径长度.

考虑二分这个最长的路径长度. 然后我们就可以让每个棋子在这个长度范围内为所欲为了!

很明显每个棋子都应该尽可能向根靠近. 我们可以直接让每个棋子尽可能向上跳. 这一步可以通过倍增预处理出向上的路径长度简单求出. 注意跳到根的子节点就不要再往上了.
经过这一步我们就会得到两类棋子, 无法再上提的棋子和能够绕过根结点到达另一棵子树的棋子.
显然能够绕过根结点到另一棵子树的棋子都分布在根结点的子节点上.

下一步, 我们找出所有没有被封上的根结点的子树, 然后考虑将能绕过根结点的棋子放到子树的根上封上这些路径. 显然让剩余路程大的棋子去离根结点距离大的子树就行了.

到此就做完了. 思路并不难想到, 但是写起来并不简单.

5. [NOIP2016 提高组] 天天爱跑步

简明题意: 给一棵无权树, 每个点有一个点权 \(w_p\). 给定一些有向路径 \((u_k,v_k)\).
对于每个结点 \(p\), 求出满足 \(p\)\((u_k,v_k)\) 上且 \(dis(u_k,p)=w_p\)\((u_k,v_k)\) 的数量, 其中 \(dis(u,v)\)\(u,v\) 间的路径长度.

6. [NOIP2018 提高组] 保卫王国

简明题意: 求带点权的树的最小点覆盖, 但是每次会指定两个点 \(a,b\), 要求必须/不能选 \(a\), 必须/不能选 \(b\).

众所周知最小点覆盖 \(=n-\) 最大独立集, 必须/不能选就是将点权更改为 \(\infty\)\(-\infty\). 然后上 ddp 板子, 时间复杂度 \(O(n\log n+q\log^2 n)/O((n+q)\log n)\).

7. [NOIP2018 提高组] 旅行 加强版

简明题意: 在一棵树或基环树上跑 dfs, 求字典序最小的 dfs 序.

一堆树论题目中混入了一棵基环树(
首先 \(m=n-1\) 即树的情况是显然的. 贪心 dfs 即可.
然后我们考虑 \(m=n\) 的基环树.
原题直接暴力删环上的边就能过, 但是加强版让我们需要想出一个 \(O(n\log n)\) 的算法.
显然我们只需要讨论走到环上的时候怎么决策.
设我们现在走到了环上的点 \(u\), 下一步能走到的点为 \(u',v_1,\cdots, v_s\), 其中 \(u'\) 是环上的点.
另外我们记当前回溯能走到的点是 \(p\).
分类讨论:

  • \(u'\) 是下一步能走到的点中最小的, 那么当然要先走 \(u'\).
  • \(\exist v_k>u'\), 则我们也是要走完 \(u'\) 之后才能走 \(v_k\).
  • \(\forall v_k, v_k<u'\), 则我们要先走完所有的 \(v_k\). 然后下面又有两种情况:
    • \(u'<p\): 正常先走 \(u'\).
    • \(u'>p\): 手动回溯, 先走 \(p\).
    • 注意我们只有一次手动回溯的机会, 之后对于上面两种情况都是先走 \(u'\).

做完了. 复杂度瓶颈在于排序.

8. [CSP-S2019] 树的重心

一句话题意: 求出无权树 单独删去每条边 得到的两个子树的重心编号和 的和.

9. [CSP-S2019] 树上的数

大 思 维 题.

题意:
有一棵树, 结点编号为 \(1,2,\cdots, n\), 每个结点上有一个 \([1,n]\) 内的整数, 且每个结点上的数互不相同.
每次可以选择一条边, 使这两个结点上的数交换. 现要对每条边进行且只进行一次操作.
试确定操作顺序使所有操作完成后, 将结点按照上面的数字进行排序时, 结点编号排列的字典序最小.

直接做是困难的, 考虑部分分.

  • 菊花图.
posted @ 2023-01-28 18:02  pjykk  阅读(38)  评论(0编辑  收藏  举报