题解:P15268 「UTOI 1C」Delirium Of Aeons
Solution
假设
现在
Subtask 3 启示我们答案至少为一条链,也就是
如果叶子要合并到主干上,也就是从叶子节点到主干的那些边都得保留,也就是说会消耗
我们来思考一下主干是什么。对于一棵树,显然是树的直径。对于树上的其他枝条,显然也有着属于这个枝条的树的直径。也就是说,树的枝条要合并到树的直径上,树的枝条上的小枝叶要合并到对应的枝条上。
这些部分有点难懂。大家可以停下来慢慢思考一下。总结一下就是叶子要合并到最长的主干上,代价就是叶子到主干的距离。可以参考一下代码实现。
:::success[code]
#include <bits/stdc++.h>
using namespace std;
int T,n,m,u,v,d[200005],ans,maxn,maxu;
vector<int> edge[200005],len;
int dfs(int u,int p,int root){
vector<int> l;
for(auto to:edge[u])
if(to!=p)
l.push_back(dfs(to,u,root));
sort(l.begin(),l.end(),greater<int>());
int tmp=u==root?2:1;
for(int i = 0;i<l.size();i++)
if(i>=tmp) len.push_back(l[i]);
if(l.size()) return l[0]+1;
return 1;
}
void dfss(int u,int p,int k){
if(k>maxn) maxn=k,maxu=u;
for(auto to:edge[u]) if(to!=p) dfss(to,u,k+1);
}
void solve(){
cin>>n>>m;
fill(d+1,d+1+n,0),ans=maxn=maxu=0,len.clear();
for(int i = 1;i<=n;i++) edge[i].clear();
for(int i = 1;i<n;i++)
cin>>u>>v,
edge[u].push_back(v),
edge[v].push_back(u),
d[u]++,d[v]++;
for(int i = 1;i<=n;i++) ans+=d[i]==1;
dfss(1,0,0);
dfs(maxu,0,maxu);
sort(len.begin(),len.end());
int cnt=n-m;
for(auto t:len)
if(cnt>=t) cnt-=t,ans--;
else break;
cout<<ans<<'\n';
}
int main(){
cin>>T;
while(T--) solve();
return 0;
}