Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 9105 | Accepted: 4122 |
Description
Input
Output
Sample Input
11 6 1 2 1 3 1 4 1 5 2 6 2 7 2 8 4 9 4 10 4 11
Sample Output
2
Hint
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn=152; const int inf=0x7ffff; int dp[maxn][maxn]; int des[maxn];//中间缓存防止自身更新 int e[maxn][maxn]; int len[maxn];//建图 int lef[maxn];//子节点+自身个数 int n,p; void dfs(int s){ lef[s]=1;//自身肯定算一个,子节点还没加上 dp[s][1]=0;//这个时候只有不切一种可能 if(len[s]==0){return ;}//没必要刻意 for(int i=0;i<len[s];i++){ int t=e[s][i]; dfs(t); fill(des,des+n+1,inf);//初始化缓存 for(int k=1;k<=lef[s];k++){ des[k]=dp[s][k]+1;//切 } for(int k=1;k<=lef[s];k++){ for(int j=1;j<=lef[t];j++){ des[k+j]=min(dp[s][k]+dp[t][j],des[k+j]);//不切 } } lef[s]+=lef[t];//加上这一枝 for(int k=1;k<=lef[s];k++){ dp[s][k]=des[k];//从缓存中取状态 } dp[s][lef[s]]=0;//不需要 } } int main(){ scanf("%d%d",&n,&p); memset(len,0,sizeof(len)); for(int i=1;i<=n;i++)fill(dp[i]+1,dp[i]+n+1,inf); for(int i=2;i<=n;i++){ int f,t; scanf("%d%d",&f,&t); e[f][len[f]++]=t; } dfs(1); int ans=dp[1][p];//1是根节点分离它不需要切 for(int i=2;i<=n;i++)ans=min(ans,dp[i][p]+1);//非根子树都要切 // printdp(); printf("%d\n",ans); return 0; }