zoukankan      html  css  js  c++  java
  • 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个。

    输出格式:

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

    输入输出样例

    输入样例#1: 
    5 2
    1 3 1
    1 4 10
    2 3 20
    3 5 20
    
    输出样例#1: 
    21

    Solution:

      本题树形$dp$板子(不过我调了好几遍啊`~`)。

      题意要留下$q$个树枝,等同于在原树上选$q$根树枝,使得树枝必须和父节点相连,且价值最大。

      那么直接套上分组背包板子,定义状态$f[i][j]$表示在$i$的子树中选$j$条边的最大价值,则不难想到状态转移方程:$f[u][j]=max(f[u][j],f[u][j-k]+f[v][k-1]+w[u,v])$(范围$jleq sizeu,;kleq min(j,sizev)$,特别注意转移时是$f[v][k-1]$(被这坑了几遍),因为在$v$子树中选边,就必须保证连通先选上$w[u,v]$这条边,所以在$v$子树中只能选$k-1$条边

      最后输出目标状态$f[n][q]$就好了。  

    代码:

    #include<bits/stdc++.h>
    #define il inline
    #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
    #define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--)
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define Min(a,b) ((a)>(b)?(b):(a))
    
    using namespace std;
    const int N=205;
    
    int n,m,rd[N],to[N],net[N],w[N],f[N][N],cnt,h[N];
    
    il void add(int u,int v,int c){
        rd[v]++,to[++cnt]=v,net[cnt]=h[u],h[u]=cnt,w[cnt]=c;
    }
    
    il int dfs(int u,int fa){
        if(rd[u]==1&&u!=1) return 1;
        int tot=0,sizev;
        for(int i=h[u];i;i=net[i])
            if(to[i]!=fa){
                sizev=dfs(to[i],u);
                tot+=sizev;
                Bor(j,1,tot) {
                    int c=Min(sizev,j);
                    For(k,1,c) f[u][j]=Max(f[u][j-k]+f[to[i]][k-1]+w[i],f[u][j]);
                }
            }
        return tot+1;
    }
    
    int main(){
        ios::sync_with_stdio(0);
        cin>>n>>m;
        int u,v,c;
        For(i,1,n-1){
            cin>>u>>v>>c;
            add(u,v,c),add(v,u,c);
        }
        dfs(1,1);
        cout<<f[1][m];
        return 0;
    }
  • 相关阅读:
    数据库操作类
    并查集的使用
    简单的图片识别,源代码
    Sql Server清理缓存代码
    京东商城商品价格获取方法
    【转】 SEO的含义与意义
    隐藏控制台窗口的方法
    MySQL存储过程详解
    常见电商B2C网站购物车的设计
    UML建模之业务处理模型(Business Process Model,BPM)
  • 原文地址:https://www.cnblogs.com/five20/p/9166513.html
Copyright © 2011-2022 走看看