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;
    }
  • 相关阅读:
    sql
    字符和字符串处理例子
    如何用火狐设置代理
    数组指针的一个小例子
    (转)数组指针和指针数组的区别
    函数
    (转)C语言指针5分钟教程
    通俗版解释网关,IP地址,ARP欺骗,DDOS攻击
    计算网络地址
    计算机网络性能指标
  • 原文地址:https://www.cnblogs.com/zeze/p/6012918.html
Copyright © 2011-2022 走看看