LINK:CF125E MST Company
难点在于构造 前面说到了求最小值 可以二分出斜率k然后进行\(Kruskal\) 然后可以得到最小值。\(mx\)为值域.
得到最小值之后还有一个构造问题 值得注意的是虽然得到的权值是最小的 也是合法的 但是此时拿到的边不一定合法。
出现这种情况的原因是最小生成树的边的权值相等了 所以白边有限那么久多余了。
实际上可以构造出了的。
考虑如何构造:
第一种是考虑最小k度生成树的做法。先将除1以外的联通块做一下。然后不断加边。
加成一颗树的时候如果不满足k度 那么再次加边 在边形成的这个环中找到除了和1相连的最大边 然后在所有的边中选取影响最小的。
一直重复是的1的度数为k.每次暴力dfs预处理一下. 复杂度\(n\cdot k+mlogm\)
值得一提的是这个做法脱离了Wqs二分 比较暴力 但是是一个比较经典的做法。
第二种是直接替换法。
二分得到ans之后 所有和1相连的边加上ans 此时可能1的度数cnt>k.
考虑利用其他边来替换和1相连的那些边 如果一条边的权值和1相连的某条边权值相同 且分属不同子树中就可以替换。
复杂度\(nlogmx+nlogn+mlogm\)复杂度算是比较优秀 正确性可以确保。
第三种是直接构造法。
还是分析本质原因 边之间的替换问题。
一个比较重要的结论是最小生成树的边的权值个数是一定的。
也就是前轮到某个权值 这种权值数量一定。同时可以得到当进行到某一种权值的时候 树的形态也是一定的。可以考虑利用权值分层处理构造。
设w[x]表示比x大的权值的和1相连的边最多的个数。
那么当前拿和1相连的边的个数就知道了 直接拿就行了 拿够了就拿其他的边 保证了后续是一定是满足的。
复杂度\(mlogm+nlogmx\)
第三种比较繁琐 第一种不够优秀 所以使用的是第二种方法。
code
//#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include