zoukankan      html  css  js  c++  java
  • 树形DP

     给一棵节点带权的树,找到一个有k个节点的子树,求这个子树的最大权值。

    dp[u][k]表示以u为根的子树中包含u结点的大小为k的子树的最大权和

      然后对u的每个子节点做分组背包,因为对于u的每个儿子,可以选择分配
       1,2,3...k-1个节点给它

     状态转移方程:

       当节点大小为K时,可以由根节点为u,子树大小为k-t, 加上根节点为v,子树大小为t的状态转移得到(v为u的子节点),即:


       dp[u][k] = max(dp[u][k] , dp[u][k-t]+dp[v][t]);//v是u的儿子节点

    
    
    #include <iostream>  
    #include <cstdio>  
    #include <cstring>  
    #include <algorithm>  
    #include <vector>  
    using namespace std;
    //简单的树形DP
    int max(int a,int b){
        return a>b?a:b;
    }
    const int inf = 1<<30;
    int n,k;
    int x[202];
    int dp[202][202];
    vector <int> List[202];
    
    void dfs(int u,int father){
        int i,j;
        for(i=0;i<List[u].size();i++)
        {
            int v=List[u][i];
            if(v==father) 
                continue;
            dfs(v,u);
            
            for(j=k;j>=1;j--)//一定要倒序
            {
                for(int t=1;t<=j;t++)
                    dp[u][j]=max(dp[u][j] , dp[u][t]+dp[v][j-t]);
            }
        }
    }
    int main(){
        scanf("%d %d",&n,&k);
        int i,j,a,b;
        for(i = 0;i <= n;i++) //清空list表
            List[i].clear();
        memset(dp,0,sizeof(dp));
        dp[0][1]=0;//以0为根节点有且只有1个节点字数的最大权重
        for(i=1;i<=n;i++){    
            scanf("%d %d",&b,&dp[i][1]);//以i为根节点有且只有1个节点字数的最大权重
            List[i].push_back(b);
            List[b].push_back(i);
        }
        k++;//多加一个0节点
        dfs(0,-1);
        printf("%d
    ",dp[0][k]);//以0为根节点有且只有m个节点字数的最大权重
        return 0;
    }
  • 相关阅读:
    事务创建函数
    实现Xshell断开连接情况下Linux命令继续执行
    MySQL UNION 操作符
    CentOS安装部署Mysql 5.7
    连接数据库
    @Results用法总结
    在Java中如何高效的判断数组中是否包含某个元素
    Java中的map集合顺序如何与添加顺序一样
    instanceof的用法
    枚举
  • 原文地址:https://www.cnblogs.com/zeze/p/6012918.html
Copyright © 2011-2022 走看看