传送门
考虑贪心,对于所有的旅游地应该靠近根结点,工厂尽可能在叶子结点或者是离根远的地方
假设全部都是工厂,那么答案就是0
那么开始遍历,按照dfs序把点变成旅游点。
如果把深度为d,子树为S的结点变成旅游点,那么除了它外的子树中,所有结点可以结果的旅游地+1,也就是加上S - 1
而对于这个点,因为它的父亲结点都是旅游点,那么贡献值就少了d - 1
那么每个点的贡献值为(S - 1 - (d - 1) = S - d)
那么就把这些值排序,求出前k个最大值和即可
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int N = 2e5 + 5;
std::vector<int> g[N];
int depth[N], siz[N];
std::vector<int> ans;
void dfs(int u, int fath = 0){
siz[u] = 1;
depth[u] = depth[fath] + 1;
for(auto v : g[u]){
if(v == fath)continue;
dfs(v, u);
siz[u] += siz[v];
}
ans.push_back(siz[u] - depth[u]);
}
int main(){
int n, k;
cin >> n >> k;
for(int i = 1; i < n; i++){
int u, v;
cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
dfs(1);
sort(ans.begin(), ans.end(), greater<int>());
long long sum = 0;
for(int i = 0; i < n - k; i++)
sum += ans[i];
cout << sum << endl;
return 0;
}