zoukankan      html  css  js  c++  java
  • 【DP合集】tree-knapsack

    Description

    给出一个 N 个节点的有根树,点编号 1 ∼ N ,编号为 i 的点有权值 v i 。请选出一个包含树根的,点数 不超过 K 的连通块,使得点权和最大。

    Input

    输入的第一行有二个整数 N , K ( K ≤ N ≤ 3000) 。 
    接下来一行 N 个整数,第 i 个数描述编号为 i 的点的父亲编号,若该数为 0 ,则表示点 i 为树根。 
    接下来一行 N 个整数,第 i 个数描述编号为 i 的点的权值。

    Output

    输出一行一个整数,描述最大的点权和。保证答案不会超过 2311231−1。

     

    题解:
    这个题目我还是建议先自行百度树形背包,不然听不懂我在说什么!(不过估计看懂后就不会听我讲了QAQ),好了,这是道树形背包的裸题,状态是显然的,dp[i][j]表示dp到i号节点可以放j个节点的最大点权和,保障连通也很简单,只要让他强制选当前i号节点就可以,接下了的问题就是转移了,显然我们可以把每棵子树单词一个不定代价和价值的背包,那么我们先把当前节点也当成一个同样的背包,然后每次将一个子树与当前的根节点的不定背包合并,然后枚举下一棵子树,没听懂没关系,代码很清楚。
     
    代码:
    #include<iostream>
    #include<stdio.h>
    #include<algorithm>
    #include<stdlib.h>
    #include<cstring>
    const int MAXN=3010;
    using namespace std;
    struct edge{
        int first;
        int next;
        int to;
    }a[MAXN*5];
    int n,m,num=0,roof;
    int dp[MAXN][MAXN];
    int W[MAXN];
     
    void cl(){
        memset(dp,0,sizeof(dp));
    }
     
    void addedge(int from,int to){
        a[++num].to=to;
        a[num].next=a[from].first;
        a[from].first=num;
    }
     
    void dfs(int now,int fa,int w){
        if(w==0) return;
        for(int i=a[now].first;i;i=a[i].next){
            int to=a[i].to;
            if(to==fa) continue;
            for(int j=1;j<=w;j++) dp[to][j]=dp[now][j];
            dfs(to,now,w-1);
            for(int j=1;j<=w;j++) dp[now][j]=max(dp[now][j],dp[to][j-1]+W[to]);
        }
    }
     
    int main(){
        cl();
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            int x;
            scanf("%d",&x);
            if(x==0) roof=i;
            else addedge(i,x),addedge(x,i);
        }
        for(int i=1;i<=n;i++) scanf("%d",&W[i]);
        dfs(roof,0,m);
        printf("%d",dp[roof][m-1]+W[roof]);
    }
     
  • 相关阅读:
    jenkins as code 与go语言学习
    VC++ 网络编程总结(一)
    Linux下的C高级编程---学习
    面试前必做4准备
    MFC视图切换大全总结
    多线程编程技术学---学习笔记--线程编程基础知识
    C语言高效编程的几招(绝对实用,绝对经典)
    汇编语言(学习笔记-----[bx]和loop)
    汇编语言(学习笔记----源程序)
    汇编语言(学习笔记----寄存器-内存访问)
  • 原文地址:https://www.cnblogs.com/renjianshige/p/7198299.html
Copyright © 2011-2022 走看看