将分组背包的思想运用到树上就ok了,注意边界条件以及子树最优值判断。
ACcode:
#include<cstdio>
#include<cstring>
const int ns=500;
const int INF=1000000000;
int n,x,y,p,top,ans;
int head[ns],to[ns],next[ns],dp[ns],v[ns];
void add(int u,int v)
{
next[top]=head[u];
to[top]=v;
head[u]=top++;
}
int Min(int a1,int a2)
{
return a1<a2?a1:a2;
}
void dfs(int rt)
{
v[rt]=0;
int tp[ns],w,e=0,t;
memset(tp,-1,sizeof(tp));
tp[0]=0;
for (int i=head[rt];i!=-1;i=next[i])
{
w=to[i];
if (v[w])
{
e++;
dfs(w);
for (int j=n;j>=0;j--)
{
t=-1;
for (int k=j;k>=0;k--)
{
if (tp[k]!=-1&&dp[j-k]!=-1)
{
if (t!=-1) t=Min(tp[k]+dp[j-k],t);
else t=tp[k]+dp[j-k];
}
}
tp[j]=t;
}
}
}
for (int i=n;i>0;i--) dp[i]=tp[i-1];
dp[0]=1;
if (dp[p]!=-1) ans=Min(ans,dp[p]+1);
}
int main()
{
while (~scanf("%d%d",&n,&p))
{
top=0,ans=INF;
memset(v,1,sizeof(v));
memset(head,-1,sizeof(head));
for (int i=1;i<n;i++)
{
scanf("%d %d",&x,&y);
add(x,y),add(y,x);
}
if (n==p) ans=0;
else dfs(1);
if (dp[p]!=-1) ans=Min(ans,dp[p]);
printf("%d\n",ans);
}
return 0;
}