• ural 1018 Binary Apple Tree


    1018. Binary Apple Tree

    Time limit: 1.0 second
    Memory limit: 64 MB
    Let's imagine how apple tree looks in binary computer world. You're right, it looks just like a binary tree, i.e. any biparous branch splits up to exactly two new branches. We will enumerate by integers the root of binary apple tree, points of branching and the ends of twigs. This way we may distinguish different branches by their ending points. We will assume that root of tree always is numbered by 1 and all numbers used for enumerating are numbered in range from 1 to N, where N is the total number of all enumerated points. For instance in the picture below N is equal to 5. Here is an example of an enumerated tree with four branches:
    2   5
      / 
      3   4
        /
        1
    
    As you may know it's not convenient to pick an apples from a tree when there are too much of branches. That's why some of them should be removed from a tree. But you are interested in removing branches in the way of minimal loss of apples. So your are given amounts of apples on a branches and amount of branches that should be preserved. Your task is to determine how many apples can remain on a tree after removing of excessive branches.

    Input

    First line of input contains two numbers: N and Q (2 ≤ N ≤ 100; 1 ≤ QN − 1). N denotes the number of enumerated points in a tree. Q denotes amount of branches that should be preserved. Next N − 1 lines contains descriptions of branches. Each description consists of a three integer numbers divided by spaces. The first two of them define branch by it's ending points. The third number defines the number of apples on this branch. You may assume that no branch contains more than 30000 apples.

    Output

    Output should contain the only number — amount of apples that can be preserved. And don't forget to preserve tree's root ;-)

    Sample

    inputoutput
    5 2
    1 3 1
    1 4 10
    2 3 20
    3 5 20
    
    21
    

    刚开始学树状dp,欢迎来喷。

    有一颗苹果树,它的树枝符合完全二叉树。每个树枝上有一些苹果。节点标号为1~N(1为根节点)。现在因为树枝太多了,需要保留q根树枝。问最多能保留多少苹果。

    题目给出的数据并没有按照跟节点到子节点的顺序给出,如何建树便一直困扰了我好久(战五渣-。-)。 最终借助结构体存放两个儿子的下标比较优美地建出来了。

    接下来讲转移。显然我们不光要考虑节点,还要考虑以该节点为根的树选择了多少条边。

    dp[t][k] : 已 t 为根的子树保留k条边(树枝)最多能保留多少条苹果。

    由此我们可以发现如果在某个节点保留了k条边,有以下两种情况。

      1:只选择一棵子树。那么dp[t][k] = max(dp[t.l][k-1] + w[t][t.l], dp[t.r][k-1] + w[t][t.r]) //意思是在该子树(左或右)选择k-1条边,并加上根节点到该子树的边。

      2:选择两颗子树。那么就存在两条固定的边(根节点到其左右孩子的边),dp[t][k] = w[t][t.l] +w[t][t.r] + max(dp[t.l][j] + dp[t.r][k - j - 2]) /*(j : 0 ~ K-2)*/ 。

           即左子树和右子树总共选择k-2条边。

    由此,输出dp[1][q]就好。

    #include <vector>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    struct Node {
        int l, r;
    }T[105];
    
    int n, q;
    int dp[105][105], map[105][105];
    
    void buildTree(int t) {//建树
        int flag = 0; 
        for (int i=0; i<=n; i++) {
            if (map[t][i] && !T[i].l && !T[t].r) {//!T[i].l不为父节点
                if (!T[t].l) T[t].l = i;
                else T[t].r = i;
                flag = 1;
            }
        }
        if (flag) {
            buildTree(T[t].l);
            buildTree(T[t].r);
        }
    }
    
    void Tdp (int s) {
        if (T[s].l == 0) return ;
        Tdp(T[s].l);
        Tdp(T[s].r);
        for (int i=1; i<=q; i++) {//转移
            dp[s][i] = max(dp[T[s].l][i-1] + map[s][T[s].l], dp[T[s].r][i-1] + map[s][T[s].r]);
            for (int j=0; j<i-1; j++) {
                dp[s][i] = max(dp[s][i], dp[T[s].l][j] + dp[T[s].r][i-j-2] + map[s][T[s].l] + map[s][T[s].r]);
            }
        }
    }
    
    int main () {
        cin >> n >> q ;
        int a, b, c;
        for (int i=1; i<n; i++) {
            cin >> a >> b >> c;
            map[a][b] = map[b][a] = c;
        }
        buildTree(1);
        Tdp(1);
        cout << dp[1][q] <<endl;
        return 0;
    }
  • 相关阅读:
    Codeforces Round #452 F. Letters Removing
    bzoj 1492: [NOI2007]货币兑换Cash
    bzoj 4016: [FJOI2014]最短路径树问题
    bzoj 2109: [Noi2010]Plane 航空管制
    bzoj 1058: [ZJOI2007]报表统计
    bzoj 1016: [JSOI2008]最小生成树计数
    bzoj 1013: [JSOI2008]球形空间产生器sphere
    bzoj 1758: [Wc2010]重建计划
    bzoj 2337: [HNOI2011]XOR和路径
    一本通1668取石子
  • 原文地址:https://www.cnblogs.com/xuelanghu/p/4276008.html
Copyright © 2020-2023  润新知