求用最小数量的边使得树上至少k个点被这些边覆盖
2≤k≤n≤105
显然,一条边覆盖两个点最好。
考虑最多能有多少边能覆盖两个点,用树形dp即可
复杂度
O(n)
#include<bits/stdc++.h>
#define LEN
using namespace std;
inline int getint(){
int x=0,p=1;
char c=getchar();
while(!isdigit(c)){
if(c=='-')p=-1;
c=getchar();
}
while(isdigit(c)){
x=(x<<3)+(x<<1)+(c^'0');
c=getchar();
}
return x*p;
}
int dp[100005][2];
struct tree{
int fa;
vector<int>son;
}t[100005];
void dfs(int cur){
dp[cur][1]=dp[cur][0]=0;
for(int i=0;i<t[cur].son.size();++i){
int v=t[cur].son[i];
dfs(v);
dp[cur][0]+=max(dp[v][1],dp[v][0]);
}
for(int i=0;i<t[cur].son.size();++i){
int v=t[cur].son[i],x;
if((x=dp[cur][0]-max(dp[v][0],dp[v][1])+dp[v][0]+1)>dp[cur][1]){
dp[cur][1]=x;
}
}
}
int main(){
int T=getint();
while(T--){
memset(dp,0,sizeof(dp));
memset(t,0,sizeof(t));
int n=getint(),k=getint();
for(int i=2;i<=n;++i){
int fa=getint();
t[fa].son.push_back(i);
t[i].fa=fa;
}
dfs(1);
int ans=max(dp[1][0],dp[1][1]);
//cout<<ans<<endl;
if(k<=ans*2){
cout<<(k+1)/2<<endl;
}
else{
cout<<ans+k-ans*2<<endl;
}
}
return 0;
}