• luogu2015 二叉苹果树


     

    1. 题目

      【题目描述】 有一棵苹果树,如果树枝有分叉,一定是分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个。

      【输出格式】 一个数,最多能留住的苹果的数量。

      【代码】

    /*
    User:Mandy.H.Y
    Language:c++
    Problem:appletree
    */ 
    
    #include<bits/stdc++.h>
    
    #define Max(x,y) (x)>(y)?(x):(y)
    #define Min(x,y) (x)<(y)?(x):(y)
    #define mem(A) memset((A),0,sizeof(A))
    
    const int maxn=102;
    
    int n,q,first[maxn],size=0,f[maxn][maxn];
    
    struct Edge
    {
        int v,w,nt;
    }edge[maxn<<1];
    
    template<typename T>inline void read(T &x)
    {
        x=0;char c=getchar();bool f=0;
        while(c<'0'||c>'9') {f|=(c=='-');c=getchar();}
        while(c>='0'&&c<='9') {x=(x<<3)+(x<<1)+(c^48); c=getchar();}
        if(f)x=-x;
    }
    
    template<typename T>void putch(const T x)
    {
        if(x>9) putch(x/10);
        putchar((x%10)|48);
    }
    
    template<typename T>inline void put(const T x)
    {
        if(x<0) putchar('-'),putch(-x);
        else putch(x);
    }
    
    void docu()
    {
        freopen("appletree.txt","r",stdin);
    }
    
    void eadd(int u,int v,int w)
    {
        edge[++size].v=v;
        edge[size].w=w;
        edge[size].nt=first[u];
        first[u]=size;
    }
    
    void readdata()
    {
        read(n);read(q);
        for(int i=1;i<n;++i)
        {
            int x,y,z;
            read(x);read(y);read(z);
            eadd(x,y,z);
            eadd(y,x,z);
        }
    }
    
    int dp(int u,int fa,int num,int ww)
    {
        if(num<=0) return 0;
        if(f[u][num]) return f[u][num];
        int v[3],j=0,w[3];
        f[u][num]+=ww;
        if(num==1) return f[u][num];
        for(int i=first[u];i;i=edge[i].nt)
        {
            int v1=edge[i].v,w1=edge[i].w;
            if(v1==fa) continue;
            v[++j]=v1;
            w[j]=w1;
        }
        if(j==0) return f[u][num];
        for(int j=0;j<num;++j)
        {
            f[u][num]=Max(f[u][num],ww+dp(v[2],u,num-j-1,w[2])+dp(v[1],u,j,w[1]));
        }
        return f[u][num];
    }
    
    void work()
    {
        put(dp(1,0,q+1,0));
    }
    
    int main()
    {
    //  docu();
        readdata();
        work();
        return  0;
    }
    非做顽石不可,哪管他敬仰暗唾
  • 相关阅读:
    20145总结
    2014515 总结
    2014514 总结
    20148总结
    20147总结
    20146总结
    20149总结
    2014512 总结
    2014513 总结
    【Visual Lisp】驱动器、目录、文件和注册表
  • 原文地址:https://www.cnblogs.com/Mandy-H-Y/p/11355027.html
Copyright © 2020-2023  润新知