luogu 1099 / bzoj 1999

原题链接

题意

给定1棵无根树,树边有正边权。

点路距\(D(u,F)\):最小化点点距

偏心距\(ECC(F)\):最大化点路距

现在限制\(F\)属于原树直径,且\(F\)的长度小于等于\(s\),求最小化偏心距。

对于\(30\)%的数据,\(5 \leq n \leq 300\)

对于\(100\)%的数据,\(5 \leq n \leq 5 \times 10^5\)

题解

这是什么神仙毒瘤题!

暴力选手:

限制\(F\)属于原树直径?原树直径这么多条,难道逐一找出再做?

干脆直接枚举\(F\)的两端点,并将\(F\)上节点标记为不可访问。从两端点进行\(DFS\)求得最长距离即可判定能否得到直径。若能得到直径,则求偏心距。

偏心距是最大的点路距,而点路距的本质是该点到该路径上,既不经过重复的边也不经过该路径上的边,故可以转化成从该路径上的节点向外\(DFS\)得到。时间复杂度:\(O(n^3)\)


优秀选手:

原树直径有多条不好做?我先来大胆猜想一发,考虑任意一条直径都是等价的。

证明?读者自证不难

性质1,1棵树中,任意两条直径都是相交的

假设两条直径不相交,一定存在某条简单路径将两条直径连起来。形如此:

KylenU.png

选择其中最长的两条分链加上用于连接的简单路径,会得到一条更长的直径,与假设矛盾。

性质2,各条直径在不相交的两端,长度分别相等(感谢::Dash::

考虑两条直径AB和CD,它们的重叠部分为EF。

Ky3ImT.png

直径最长,新的组合长度不能超过直径长度。因此\(DF = BF,AE = EC\)

推论:在任意一条直径上求最小偏心距都是等价的

偏心距的定义为所有点到已选定路径的距离最大值。本质上是路径上各点到非路径上各点的距离最大值。

根据直径的最长性,偏心距为路径上的点到某个直径端点的距离的最大值。

当选取的路径不包含公共部分时,举个栗子,在\(AE\)上取点\(P,Q\)\(Q\)更靠\(E\)),则偏心距为\(max(CQ,DQ)\)

当选取的路径包含公共部分时,举个栗子,在\(AE\)上取点\(P\)\(BF\)上取点\(Q\)时,偏心距为\(max(CE,DF)\)。同理,\(CE\)上取点\(P\)\(DF\)上取点\(Q\),那么偏心距为\(max(AE,BF)\)。根据\(AE = CE\)\(BF = DF\),无论端点取在哪一条直径上,偏心距都相等。

两种情况进行比对,举在\(AB\)上取路径的栗子来说,由于\(CQ > CE且DQ > DF\),端点都取在\(AE\)上一定不如1个取在\(AE\)上1个取在\(BF\)上优。同理,端点取在任意非公共部分的结果一定不优于包含公共部分的结果,即使枚举了也不可能纳入最优解中。真正纳入最优解的包含公共部分的情况偏心距又相等,因此在任意一条直径上求最小偏心距都是等价的。

由上述论证也可以发现,假设我们固定路径在直径上的左端点,那么右端点离左端点越远越好。枚举路径左端点,贪心地求出路径长度在\(s\)之内时的最右端点,再\(DFS\)计算偏心距即可。时间复杂度\(O(n^2)\)

一种优化方法是考虑答案的单调性

一条路径的偏心距,等于该路径两端点与其所在直径两端点的距离 与 该路径上点不经过所在直径上点 到达 非所在直径上点的距离 的最大值。由此可知,对于答案而言,路径端点离直径端点越近越好;但又需要保证两端点距离不超过\(s\),故不能离直径端点太近。

不妨采用二分答案的技巧,二分\(mid\)表示偏心距大小,判断偏心距能否不超过\(mid\)。具体地,从两个端点各自开始,在与直径端点距离不超过\(mid\)的前提下不断向中心移动;移动完毕后\(DFS\)求偏心距,若偏心距小于等于\(mid\)且两端点距离小于等于\(s\),则说明\(mid\)合法,\(hi = mid\);否则不合法,\(lo = mid\)。时间复杂度\(O(log(\sum v)(n + m))\)

另一种优化方法,保留\(O(n^2)\)解法中端点双指针移动的过程,优化求解偏心距的过程,即不进行重复的\(DFS\)

上文也提到,偏心距仅由两部分组成,一种是路径端点到选定直径的端点的距离,每次可以\(O(1)\)求解;另一种是路径上的各个点 不经过选定直径上的点 到达的最远点距 的最大值,不难发现 各点 不经过选定直径上的点 到达的最远点距只与你选定的直径有关,与你选择的路径端点无关,只需1次\(DFS\)即可求得,设为\(d[u]\)

设选定直径上点为\(u_1...u_t\),选定的路径端点为\(u_i,u_j\),偏心距为\(max(max(d[u_i \rightarrow u_j]),dis(1,u_i),dis(u_j,u_t))\)局部最大值\(max(d[u_i \rightarrow u_j])\)使用单调队列维护,时间复杂度\(O(n)\)

进一步优化。结合推论的证明可以发现,当\(max(d[u_i \rightarrow u_j])\)成为答案时,路径一定包含了直径的公共部分,偏心距大小是个定值,不随路径端点的改变而改变;故求解式\(max(max(d[u_1 \rightarrow u_t]),dis(1,u_i),dis(u_j,t))\)能够保证答案的正确性,且只需维护1个变量,效率更高。时间复杂度\(O(n)\)

[代码见此](https://github.com/littlewyy/OI/blob/master/luogu 1099.cpp)

posted @ 2019-10-27 22:21  littlewyy  阅读(162)  评论(0编辑  收藏  举报