「SHOI2008」仙人掌图 - 仙人掌DP,单调队列
给定一个仙人掌图,求其直径。
题解
仙人掌什么的好难呀,看了好长时间的题解才理解究竟要怎么做,不过感觉还是蛮有趣的,处理树上和环上的方式也很巧妙,那么我就简单口胡一下。。
选一个点为根,DFS 整棵树,设 表示DFS树中以节点 为根的子树的点集在原图中的诱导子图中以 开始的最长路径。
若不考虑环,记 为节点 的儿子集合,则有 。
然而由于环的存在,会使得某些点之间的距离变小,从而影响维护到的 值的正确性,所以我们在转移 时需要满足转移到他的节点 不和 处在同一个环上,即不在同一个环上转移 。
判断环的问题,只需要在 DFS 的时候按照 Tarjan 算法的流程记录每个点的 和 即可。
由于仙人掌的特性,以及 DFS 的过程,对于每个环都可以找到一个深度最小的点,我们称这个点为 最高点,显然的,这个环的祖先的 值的更新需要且仅需要用到最高点的 值,所以对于整个环,在用环上的节点的不在环上的子节点更新过自身的 后,只需要再更新最高点的 值即可。
设最高点为 ,则 由环上节点转移的方式为 ,其中 和 在同一环上,
以上内容全部是关于 值的更新,接下来要说的是更新答案的方式。
对于桥上的答案,我们在 DFS 过程中更新 值的同时更新答案,设答案为 ,目前正在更新 值的节点为 ,则此时有 。注意要在尝试从节点 转移 值之前更新答案,否则不能涵盖所有情况,还可能导致状态出现错误。
显然地,环上的节点也可以用来更新答案。对于环上的节点 来说,其导致的答案的形式应该是 。设 为节点 在环上的编号(编号按照 DFS树 上的深度为顺序),则原式可以改写成为 。如果按照深度为顺序转移答案,并且保证在枚举到节点 时转移区间连续并且长度不超过环长度的一半,就可以使用单调队列维护 的值来优化转移。
具体细节详见代码。
代码
|
Author: Sulfur6
Origin: http://sulfur6.github.io
Link: http://sulfur6.github.io/bzoj-1023/
本文采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可