标签:
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
Source
正解:树形DP
解题报告:
感觉自己DP很萎,最近练一下DP。
f[i][j]记录以i为根结点的子树切出j个节点的最小代价,转移的话也很简单,f[x][j] = min{f[x][j],f[son[x][i]][k]+f[x][j-k]-2},减2是因为要减去算了两次的x到son[x][i]的那条边。
递归转移就可以了。
题解传送门:http://www.cnblogs.com/celia01/archive/2012/08/02/2619063.html
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<cstdlib> 6 #include<algorithm> 7 #include<vector> 8 using namespace std; 9 const int MAXN = 151; 10 int f[MAXN][MAXN];//f[i][j]记录以i为根结点的子树切出j个节点的最小代价 11 int du[MAXN]; 12 vector<int>w[MAXN]; 13 int n,p; 14 int ans; 15 int root; 16 17 inline int getint(){ 18 char c=getchar(); int w=0,q=0; 19 while(c!=‘-‘ && ( c<‘0‘ || c>‘9‘)) c=getchar(); 20 if(c==‘-‘) c=getchar(),q=1; 21 while(c>=‘0‘ && c<=‘9‘) w=w*10+c-‘0‘,c=getchar(); 22 return q?-w:w; 23 } 24 25 inline void dfs(int x){ 26 if(x==root) f[x][1]=w[x].size(); 27 else f[x][1]=w[x].size()+1;//父边 28 29 for(int i=0;i<w[x].size();i++) dfs(w[x][i]); 30 31 for(int i=0;i<w[x].size();i++) 32 for(int j=p;j>=0;j--) 33 for(int k=0;k<=j;k++) { 34 if(f[x][k]!=MAXN && f[w[x][i]][j-k]) { 35 f[x][j]=min(f[x][j],f[x][k]+f[w[x][i]][j-k]-2); 36 } 37 } 38 } 39 40 int main() 41 { 42 n=getint(); p=getint(); 43 44 int x,y; 45 for(int i=1;i<n;i++) { 46 x=getint(); y=getint(); 47 w[x].push_back(y); du[y]++; 48 } 49 50 for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) f[i][j]=MAXN; 51 52 for(int i=1;i<=n;i++) if(du[i]==0) { root=i; dfs(i); break; } 53 54 ans=MAXN; 55 for(int i=1;i<=n;i++) ans=min(ans,f[i][p]); 56 57 printf("%d",ans); 58 59 return 0; 60 }
标签:
原文地址:http://www.cnblogs.com/ljh2000-jump/p/5574523.html