CF1119F - Niyaz and Small Degrees
CF1119F - Niyaz and Small Degrees
题目大意
给定一棵带权树,对于每个 \(k\in[0,n-1]\)
求出删除一个权值最小的边集使得没有一个点度数 \(>k\)
分析
单个 \(k\)
考虑对于单个 \(k\) 的计算,可以有如下 \(O(n)\) 的 \(dp\) 做法
令 \(dp_{u,0/1}\) 表示对于 \(u\) 子树内的点已经确定合法, \(0/1\) 表示连向父亲的边是否断掉
实际上我们需要在连向儿子的边中选择若干条断掉
也就是取若干 \(v\in son_u,dp_{v,1}\) 和若干 \(dp_{v,0}\)
实际上只需要考虑 \(dp_{v,1}-dp_{v,0}\) 差值的前 \(d\) 小,其中 \(d=deg_u-k(-1)\)
用std::nth_element
即可实现 \(O(n)\) 计算
所有 \(k\)
考虑对于 \(k\) ,只有 \(deg_u>k\) 的 \(u\) 才会考虑对于它周围的边删除
我们称对于 \(k\) 这样的节点 \(u\) 为关键点,其集合为 \(S_k\)
换句话说, \(u\) 只有在 \(k\in[0,deg_u-1]\) 的 \(deg_u\) 的 \(k\) 中被计算答案
而又知道 \(\sum deg_u=2n-2\) ,故对于所有 \(k\) 考虑关键点的数量之和为 \(O(n)\)
但是实际实现上,因为这样的 \(u\) 构成若干联通子图,且那些与关键点所连的非关键点需要处理边的贡献
显然一个非关键点 \(dp_{v,0}=0,dp_{v,1}=w_v\) , \(w_v\) 为父边权值
我们需要在 \(\{w_v|v\in son_u-S_k\}\) 和 \(\{dp_{v,1}-dp_{v,0}|v\in son_u\cap S_k\}\) 中取前 \(d\) 小,可以用线段树 \(O(n\log n)\) 维护
如果使用基数排序+链表+懒标记做删除和 \(k\) 大操作,查询 \(k\) 大部分复杂度为 \(O(n)\) ,但是还是要sort \(dp_{v,1}-dp_{v,0}\)
1 | const int N=2.5e5+10,U=1e6,M=N*40; |