「一本通 5.2 练习 2」旅游规划
题目描述
W 市的交通规划出现了重大问题,市政府下定决心在全市各大交通路口安排疏导员来疏导密集的车流。但由于人员不足,W 市市长决定只在最需要安排人员的路口安排人员。
具体来说,W 市的交通网络十分简单,由 n 个交叉路口和 n−1 条街道构成,交叉路口路口编号依次为 0,1,⋯ ,n−10,1,\cdots ,n-10,1,⋯,n−1 。任意一条街道连接两个交叉路口,且任意两个交叉路口间都存在一条路径互相连接。
经过长期调查,结果显示,如果一个交叉路口位于 W 市交通网最长路径上,那么这个路口必定拥挤不堪。所谓最长路径,定义为某条路径 p=(v1,v2,v3,⋯ ,vk)p=(v_1,v_2,v_3,\cdots,v_k)p=(v1,v2,v3,⋯,vk),路径经过的路口各不相同,且城市中不存在长度大于 kkk 的路径,因此最长路径可能不唯一。因此 W 市市长想知道哪些路口位于城市交通网的最长路径上。
输入格式
第一行一个整数 n;
之后 n−1 行每行两个整数 u,v,表示 u 和 v 的路口间存在着一条街道。
输出格式
输出包括若干行,每行包括一个整数——某个位于最长路径上的路口编号。为了确保解唯一,请将所有最长路径上的路口编号按编号顺序由小到大依次输出。
样例
样例输入
1 | 10 |
样例输出
1 | 0 |
数据范围与提示
对于全部数据,
题解
一句话题意,求一棵树上所有直径上的所有点。
我们先想想如何判断一个点是否是直径上的点。
考虑它在一棵树上延伸的最长链和次长链,假设这两个加起来等于直径,那它就是直径上的点。
假如它小于直径上,我们是否能证明他不在直径上呢?
显然反证法,假设它在一条直径上,直径两端点必定有一个是他的最长链端点,否则这就不是直径了。
假设另一个端点不是直径端点,设它次长链端点为V,显然V和最长链端点构成新的直径,与假设矛盾。
也就是说一个点在直径上,它的最长链和次长链端点就是直径两个端点。
因此我们只需要知道每个点能伸展的最长链和次长链即可。
假设我们以任意点为根,树上一个点的最长链和次长链必定是子树内最长链,子树内次长链,子树外最长链(子树外次长链无论如何能被子树内最长链代替,没有用)中的二者。
这就是一个典型的换根dp,或者说up and down
假设以s为根,先up出以s为根的有根树每个点子树内的最长链和次长链。
up完后,我们可以顺便求出直径长度(直径必定是某个点子树内的最长链和次长链之和,假如不是,那这条直径上的点就造成了矛盾)。
这时候我们假如枚举根来继续这样求,时间复杂度
超时的原因是我们没有考虑根转移后状态的联系。
我们以最顶端为根,已经完成了up的过程。
这时候我们想向子节点转移。
显然以子节点为根最长链和次长链只有上述说的三种情况。但是要注意这个原根的最长链可能就是由这个节点转移过来的
因此我们在up最长链的时候记录最长链由哪个子节点转移过来的。down的时候假设当前子节点是原根最长链的转移者,就用根的次长链来更新,实现常数换根转移。
总复杂度
Code:
1 |
|
Ps:写的时候又犯了睿智错误,把变量和数组名写错了。。。