• P2015 二叉苹果树


     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

    分析

    >:<自己做出来的第一道树形动规题,纪念!!!

    树形动规,+背包

    如果想要保留下树枝a,那么首先要留下a的父亲的树枝。

    所以:dp[u][j]以u为根的子树中留下了j条(一定是联通的),的最大价值。

    那么从叶推到根即可。

    转移方程:dp[u][j] = max(dp[u][j],dp[v][k]+dp[u][j-k-1]+w);

    就是从子树v中选取k条树枝,从u树其他的子树中选取j-k-1条,再加上连接v的那一条 合起来 就是从树u中选j条边的最大价值。

    code

     1 #include<cstdio>
     2 #include<algorithm> 
     3 #include<cstring>
     4 
     5 using namespace std;
     6 
     7 const int N = 110;
     8 
     9 struct Edge{
    10     int to,nxt,w;
    11 }e[10010];
    12 int head[10010],tot;
    13 
    14 int dp[N][N];
    15 int Sum,n,m;
    16 
    17 inline int read() {
    18     int x = 0,f = 1;char ch = getchar ();
    19     for (; ch<'0'||ch>'9'; ch = getchar())
    20         if (ch=='-') f = -1;
    21     for (; ch>='0'&ch<='9'; ch = getchar())
    22         x = x*10+ch-'0';
    23     return x*f;
    24 }
    25 
    26 inline void add_edge(int u,int v,int w) {
    27     e[++tot].to = v,e[tot].w = w,e[tot].nxt = head[u],head[u] = tot;
    28 }
    29 
    30 void dfs(int u,int fa) {
    31     for (int i=head[u]; i; i=e[i].nxt) {
    32         int v = e[i].to,w = e[i].w;
    33         if (v==fa) continue;
    34         dfs(v,u);
    35         for (int j=m; j>=1; --j) 
    36             for (int k=0; k<j; ++k) 
    37                 dp[u][j] = max(dp[u][j],dp[v][k]+dp[u][j-k-1]+w);
    38     }
    39 }
    40 int main() {
    41     
    42     n = read(),m = read();
    43     for (int a,b,c,i=1; i<n; ++i) {
    44         a = read(),b = read(),c = read();
    45         add_edge(a,b,c),add_edge(b,a,c);
    46     }
    47     
    48     dfs(1,0);
    49     printf("%d",dp[1][m]);
    50     
    51     return 0;
    52 }
  • 相关阅读:
    阅读计划
    第一课 课堂练习总结
    人月神话读后感
    软件工程概论11-软件演化
    【HDU4366】【DFS序+分块】Successor
    【转载】【元胞自动机】生命游戏(时间简史)
    【BZOJ2741】【块状链表+可持久化trie】FOTILE模拟赛L
    【BZOJ3295】【块状链表+树状数组】动态逆序对
    【HDU4391】【块状链表】Paint The Wall
    【POJ2887】【块状链表】Big String
  • 原文地址:https://www.cnblogs.com/mjtcn/p/7730031.html
Copyright © 2020-2023  润新知