Ural-1018 Binary Apple Tree(树形dp+分组背包)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;

const int maxn = 100;
int dp[maxn][maxn]; //dp[i][j]表示以i为根,保留j个点的最大权值。
int N,Q;
int G[maxn][maxn];
int num[maxn];   //以i为根的树的节点个数。

//这里处理的时候要注意可以把边的权值压倒儿子节点。
void dfs(int u,int fa){
    num[u] = 1;
    for(int v=1;v<=N;v++){
        if(!G[u][v] || v == fa)  continue;

        dfs(v,u);
        num[u] += num[v];
    }

    for(int v=1;v<=N;v++){    //相当于分组k。
        if(!G[u][v] || v == fa)  continue;

        for(int i=num[u];i>0;i--){     //相对于下面的V -> 0
            for(int j=1;j<i&&j<=num[v];j++)    //枚举组k中的元素。
                dp[u][i] = max(dp[u][i],dp[u][i-j]+dp[v][j]+G[u][v]);
        }
    }
}
/**  
f[k][v]表示前k组物品花费费用v能取得的最大权值
f[k][v]=max{f[k-1][v],f[k-1][v-c[i]]+w[i]|物品i属于组k}
分组背包一维数组的伪代码:
for 所有的组k
    for v=V..0
        for 所有的i属于组k
            f[v]=max{f[v],f[v-c[i]]+w[i]}
**/
int main()
{
    cin>>N>>Q;
    memset(G,0,sizeof(G));
    memset(dp,0,sizeof(dp));
    for(int i=1;i<N;i++){
        int u,v,w;
        scanf("%d %d %d",&u,&v,&w);
        G[u][v] = G[v][u] = w;
    }
    dfs(1,-1);
    printf("%d
",dp[1][Q+1]);
}
View Code
原文地址:https://www.cnblogs.com/acmdeweilai/p/3320376.html