• P2015 二叉苹果树(树上背包)


    题目描述

    有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点)

    这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1。

    我们用一根树枝两端连接的结点的编号来描述一根树枝的位置。下面是一颗有4个树枝的树

    2   5
      / 
      3   4
        /
        1
    

    现在这颗树枝条太多了,需要剪枝。但是一些树枝上长有苹果。

    给定需要保留的树枝数量,求出最多能留住多少苹果。

    输入格式

    第1行2个数,N和Q(1<=Q<= N,1<N<=100)。

    N表示树的结点数,Q表示要保留的树枝数量。接下来N-1行描述树枝的信息。

    每行3个整数,前两个是它连接的结点的编号。第3个数是这根树枝上苹果的数量。

    每根树枝上的苹果不超过30000个。

    输出格式

    一个数,最多能留住的苹果的数量。

    题解:

    非常入门的树上背包问题,注意跑01背包的时候一定一定要从大到小遍历容量!!!

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1010;
    typedef long long ll;
    int dp[maxn][maxn];//dp(i,j)表示在以i为根的子树里选择j个枝条的最优解 
    int n,q;
    struct node {
        int u,v,w,nxt;
    }edge[maxn];
    int head[maxn];
    int tot;
    int size[maxn];//以i为根的子树的节点数量,枝条为子树节点数-1 
    void addedge (int u,int v,int w) {
        edge[tot].u=u;
        edge[tot].v=v;
        edge[tot].w=w;
        edge[tot].nxt=head[u];
        head[u]=tot++;
        
        edge[tot].u=v;
        edge[tot].v=u;
        edge[tot].w=w;
        edge[tot].nxt=head[v];
        head[v]=tot++;
    }
    void dfs1 (int u,int pre) {
        size[u]=1;
        for (int i=head[u];i!=-1;i=edge[i].nxt) {
            int v=edge[i].v;
            if (v==pre) continue;
            dfs1(v,u);
            size[u]+=size[v];
        }
    }
    void dfs2 (int u,int pre) {
        for (int i=head[u];i!=-1;i=edge[i].nxt) {
            int v=edge[i].v;
            if (v==pre) continue;
            dfs2(v,u);
            for (int j=size[u];j>=0;j--) {
                for (int k=size[v]-1;k>=0;k--) {
                    if (j>=k+1) 
                        dp[u][j]=max(dp[u][j],dp[u][j-k-1]+dp[v][k]+edge[i].w);
                }
            }
        }
    }
    int main () {
        scanf("%d%d",&n,&q);
        for (int i=1;i<=n;i++) head[i]=-1;
        tot=0;
        for (int i=1;i<n;i++) {
            int x,y,w;
            scanf("%d%d%d",&x,&y,&w);
            addedge(x,y,w);
        }
        dfs1(1,0);
        dfs2(1,0);
        int ans=0;
        for (int i=0;i<=min(q,size[1]);i++) ans=max(ans,dp[1][i]);
        printf("%d
    ",ans);
    }
  • 相关阅读:
    如何进入docker 使用root用户的方式
    阿里云服务搭建nginx并配置
    阿里云容器部署Redis集群
    Redis运维利器 -- RedisManager
    远程连接-使用SSH密钥对远程登录阿里云云服务器
    第1课:SQL注入原理深度解析
    数据库设计三大范式
    linux指令大全(归类整理)
    linux目录结构
    linux-创建/使用快照/克隆(类似windows中备份还原)
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/13503370.html
Copyright © 2020-2023  润新知