[树] [贪心] CF1976F Remove Bridges
posted on 2024-06-24 05:22:15 | under | source
upd:差不多一年后重新看这题,发现完全是套路啊。
题意:\(n\) 个点的树,以 \(1\) 为根,且 \(1\) 只有一个儿子。可以加 \(k\) 条边,要满足割边下端的子树内不存在非割边,对 \(k\in [1,n)\),求最少割边数量。
考虑加入边 \((u,v)\),等价于让树上 \(u\to v\) 路径的所有边变成非割边。那么这就变成了染色问题,选择 \(k\) 条路径染色,满足未被染色的边下面的所有边也未被染色,并且染色边尽量多。
可以发现,选取路径的两端必然是叶子节点或 \(1\),否则可以不断向下伸长路径,显然这不会影响合法性。因为从完整的子树中抽出一条顶端到叶子的链,剩下的也是完整子树。
注意到 \(1\) 只有一个儿子,所以 \(k=1\) 的答案是 \(1\) 到叶子的一条最长链。
原思路
对于一般情况,可以发现原树被已染色的边,划分为多个完整的、未被染色的子树,不难想到贪心:从中选取两条最长链拼接,最长是指未被染色的边尽量多。
假如选取的两条链来自不同子树,那么其构成的路径一定合法。但是来自同一棵子树怎么办?假设之前操作了 \((u,v)\),现在想操作 \((x,y)\),可以发现,更改操作为 \((u,x),(v,y)\) 后,就变得合法了。
所以可以拿个优先队列存剩下所有子树的最长链,除第一次以外,均选 \(2\) 条最长链即可。由于每个点只被遍历一次、加入一次,所以复杂度 \(O(n\log n)\)。
不难感性理解,口胡下正确性:交换(时间上)相邻两条链的选取顺序,不会影响合法性,所以可以交换使得选取的链长递减,即每次选最长链。
新思路
无论怎么操作,操作端点集合一定是至多 \(2k\) 个叶子。有经典结论:可以用不超过 \(k\) 条链,恰好覆盖 \(2k\) 个叶子的虚树。这是覆盖点数的上界了,同时一定满足题意(以虚树的视角看待,就是链上挂着一些完整子树),所以这么干。
这题甚至傻乎乎地告诉你 \(1\) 一定被操作,那就更容易了,经典长剖贪心即可。\(O(n\log n)\) 或 \(O(n)\)。
代码
#include<bits/stdc++.h>
using namespace std;
#define pir pair<int, int>
const int N = 3e5 + 5;
int T, n, k, u, v, fa[N], ans;
int f[N], leaf[N];
vector<int> to[N];
struct node{int u, leaf, w;};
inline bool operator < (const node& A, const node& B) {return A.w < B.w;}
priority_queue<node> s;
inline void init(int u){
f[u] = 0, leaf[u] = u;
for(auto v : to[u])
if(v ^ fa[u]){
fa[v] = u, init(v);
if(f[v] + 1 > f[u]) f[u] = f[v] + 1, leaf[u] = leaf[v];
}
}
inline void upd(node p){
int u = p.u, pos = p.leaf, lst = -1; ans -= p.w;
while(lst != u){
for(auto v : to[pos])
if(v != lst && v != fa[pos]) s.push({v, leaf[v], f[v] + 1});
lst = pos, pos = fa[pos];
}
}
inline void doit(){
if(!s.empty()){
node A = s.top(); s.pop();
upd(A);
}
}
signed main(){
cin >> T;
while(T--){
while(!s.empty()) s.pop();
scanf("%d", &n), ans = n - 1;
for(int i = 1; i <= n; ++i) to[i].clear();
for(int i = 1; i < n; ++i) scanf("%d%d", &u, &v), to[u].push_back(v), to[v].push_back(u);
init(1), s.push({1, leaf[1], f[1]});
for(int i = 1; i < n; ++i){
doit();
if(i != 1) doit();
printf("%d ", ans);
}
printf("\n");
}
return 0;
}

浙公网安备 33010602011771号