题解:uoj938 方片骑士

题意:给你一棵树,定义一次操作为选择一对相邻点 \((u, v)\),令 \(u\) 连接除 \(u\)\(v\) 的所有邻居,然后将 \(v\) 相连的边全部删去。给出一棵树,问最小高度为多少的满二叉树,可以通过上述操作得到。

做法:

我们不妨反着考虑,改成将一个点的一些邻居和自己拆开,并在中间加一个点将他们连起来,这样会更好理解。

首先如果是有根的,那么非常简单,我们考虑 \(dp_u\) 代表对于节点 \(u\),我们最少需要多少高度的满二叉树才可以得到。

考虑转移:

  1. 如果 \(u\) 没有儿子,那么显然答案是 \(1\).

  2. 如果 \(u\) 只有一个儿子,那么你肯定是将其中一个枝删光了,所以答案是 \(dp_{v} + 1\)

  3. 如果有多于一个儿子,那么最小就应该是 \(\log_2{\sum_{v \in son_u} 2^{dp_v}}\)。实际实现时,我们可以用最小的两个子树去相合并,本质就是二进制加法。

这样我们就可以解出来对于节点 \(1\) 的答案。

但是我们现在是无根树,怎么做呢?

很经典的套路,换根就行,我们可以用线段树或者其他的方式维护一下这个一坨加总的答案,但是实际上有更方便的写法,因为我们只用求出所有根的最小值,我们可以只用递归 \(dp\) 值最大的那一个儿子。

这里口胡一个证明,考虑节点 \(u\) 为根的 \(dp\) 答案,那么转移到 \(v\),就需要剃掉 \(v\) 这个子树,如果不剃最大的,这里就不可能去将 \(dp_u\) 下去的这一部分的位数减小的,保底是不会差于 \(dp_u\) 了,但是最大的那个是有可能造成退位的,所以选择最大的是最好的。

posted @ 2025-07-11 22:52  LUlululu1616  阅读(99)  评论(3)    收藏  举报