二叉苹果树(codevs 5565)树形DP

题目描述 Description

      有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点)这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1。我们用一根树枝两端连接的结点的编号来描述一根树枝的位置。现在这颗树枝条太多了,需要剪枝。但是一些树枝上长有苹果。
       给定需要保留的树枝数量,求出最多能留住多少苹果。

 

输入描述 Input Description

第1行2个数,N和Q(1<=Q<= N,1<N<=100)。
N表示树的结点数,Q表示要保留的树枝数量。接下来N-1行描述树枝的信息。
每行3个整数,前两个是它连接的结点的编号。第3个数是这根树枝上苹果的数量。
每根树枝上的苹果不超过30000个。

 

输出描述 Output Description

剩余苹果的最大数量。

 

样例输入 Sample Input

5 2

1 3 1

1 4 10

2 3 20

3 5 20

 

样例输出 Sample Output

21

 

数据范围及提示 Data Size & Hint

对于20%数据 n<=20;

对于100%数据1<N<=100,1<=Q<= N.


所遇到的问题:给出的节点没有父子关系,需要建双向边走dfs的时候判断,这部分由其注意,要先判断是否回父,在更新父亲节点
 

代码如下

#include<stdio.h>
#include<algorithm>
using namespace std;

int n,q,cnt,f[210][210],fa[210],first[210];
struct Edge{
    int to,next,val;
}edge[210];

void add(int from,int to,int val)
{
    edge[++cnt].to=to;
    edge[cnt].val=val;
    edge[cnt].next=first[from];
    first[from]=cnt;
}

void dfs(int from)
{
    for(int i=first[from];i;i=edge[i].next) {
        int to=edge[i].to;
        if(to == fa[from]) continue;
        fa[to]=from;
        dfs(to);
        for(int j=q;j>=1;--j)//采用倒推,j为总边数
            for(int k=0;k<j;++k)//k为子节点支数,不能超过总支数 
                f[from][j]=max(f[from][j],f[to][k]+f[from][j-k-1]+edge[i].val);//f[to][k] 子节点拥有 k 支时的 val, f[from][j-k-1] 父节点剩余支的 val,edge[i].val当前支的val 
    }
}


int main()
{
    scanf("%d%d",&n,&q);
    for(int i=1;i<n;++i) {
        int from,to,val;
        scanf("%d%d%d",&from,&to,&val);
        add(from,to,val);
        add(to,from,val);
    }
    dfs(1);
    printf("%d",f[1][q]);
    return 0;
}

 

二叉苹果树(codevs 5565)树形DP

上一篇:Android手机流量分析工具介绍


下一篇:ios 视图既显示阴影又有圆角实现