URAL1018 Binary Apple Tree(树形DP)
题目大概说一棵n结点二叉苹果树,n-1个分支,每个分支各有苹果,1是根,要删掉若干个分支,保留q个分支,问最多能保留几个苹果。
挺简单的树形DP,因为是二叉树,都不需要树上背包什么的。
- dp[u][k]表示以u结点为根的子树保留k个分支最多能有的苹果数
- 转移就是左子树若干个,右子树若干个转移。。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 #define MAXN 111 6 struct Edge{ 7 int v,w,next; 8 }edge[MAXN<<1]; 9 int NE,head[MAXN]; 10 void addEdge(int u,int v,int w){ 11 edge[NE].v=v; edge[NE].w=w; edge[NE].next=head[u]; 12 head[u]=NE++; 13 } 14 int n,q,d[MAXN][MAXN]; 15 void dp(int u,int fa){ 16 d[u][0]=0; 17 int lson=-1,rson=-1,w1,w2; 18 for(int i=head[u]; i!=-1; i=edge[i].next){ 19 int v=edge[i].v; 20 if(v==fa) continue; 21 if(lson==-1) lson=v,w1=edge[i].w; 22 else rson=v,w2=edge[i].w; 23 dp(v,u); 24 } 25 if(lson==-1) return; 26 if(rson==-1){ 27 for(int i=0; i<q; ++i){ 28 if(d[lson][i]==-1) continue; 29 d[u][i+1]=max(d[u][i+1],d[lson][i]+w1); 30 } 31 return; 32 } 33 for(int i=0; i<=q; ++i){ 34 if(d[lson][i]==-1) continue; 35 for(int j=0; j<=q-i; ++j){ 36 if(d[rson][j]==-1) continue; 37 if(i+j+2<=q) d[u][i+j+2]=max(d[u][i+j+2],d[lson][i]+d[rson][j]+w1+w2); 38 if(i==0 && j+1<=q) d[u][j+1]=max(d[u][j+1],d[rson][j]+w2); 39 if(j==0 && i+1<=q) d[u][i+1]=max(d[u][i+1],d[lson][i]+w1); 40 } 41 } 42 } 43 int main(){ 44 int a,b,c; 45 while(~scanf("%d%d",&n,&q)){ 46 NE=0; 47 memset(head,-1,sizeof(head)); 48 for(int i=1; i<n; ++i){ 49 scanf("%d%d%d",&a,&b,&c); 50 addEdge(a,b,c); 51 addEdge(b,a,c); 52 } 53 memset(d,-1,sizeof(d)); 54 dp(1,1); 55 printf("%d\n",d[1][q]); 56 } 57 return 0; 58 }