我才发现我这么水。原打算随便再找道题早上热身,结果WA一直到现在。改了一天,结果发现是最白痴的错误。
这道题本质上还是树形的背包,但是枚举的时候要多考虑以某儿子为根的树被整个砍掉的情况。
//By YY_More
#include<cstdio>
#include<iostream>
using namespace std;
struct edge{
int point;
edge *next;
};
edge *g[151];
int N,P,x,y,root,F[151][151],goin[151];
int INF=200;
void insert(int father,int son){
edge *p=new edge;
goin[son]++;
(*p).point=son;
(*p).next=g[father];
g[father]=p;
}
void dp(int x){
edge *p=g[x];
F[x][1]=0;
while (p!=NULL){
dp((*p).point);
for (int i=P;i>0;i--){
if (F[x][i]==INF) continue;
for (int j=1;j<=P-i;j++){
if (F[(*p).point][j]==INF) break;
if (F[(*p).point][j]+F[x][i]<F[x][i+j]) F[x][i+j]=F[(*p).point][j]+F[x][i];
}
F[x][i]++;
}
p=(*p).next;
}
}
int main(){
scanf("%d%d",&N,&P);
for (int i=1;i<N;i++){
scanf("%d%d",&x,&y);
insert(x,y);
}
for (int i=1;i<=N;i++)
if (goin[i]==0) root=i;
fill(&F[0][0],&F[151][151]+1,INF);
dp(root);
int ans=F[root][P];
for (int i=1;i<=N;i++)
if (F[i][P]!=INF&&F[i][P]+1<ans) ans=F[i][P]+1;
printf("%d\n",ans);
return 0;
}
浙公网安备 33010602011771号