• $Luogu$ $P2015$ 二叉苹果树


    链接

    背景

    (Luogu) (P1122/Codevs5565)

    题意

    给定一棵 (n) 个节点的以 (1) 号点为根节点的树的 (n-1) 条边及权值 ((x_i,y_i,w_i)) ,求砍掉一些枝条后留下 (q) 条边的最大边权和。

    解法

    也不是树形 (dp) 模板。还是习题。
    由于这棵树是二叉树,有一个优美的性质:某棵子树内保留的树枝只能由左右子树得到(这不是废话吗)。
    考虑转换题意,砍掉一些枝条后留下 (q) 条边也即留下 (q+1) 个点且必须包含根。
    于是就可以设 (f_{x,i}) 表示以 (x) 节点为根的子树留下 (i) 个点的最大边权和。
    这个时候就要考虑继续转换题目了。由于根必选,所以 (n-1) 条边完全可以转化成剩下 (n-1) 个点的权值(每个点到它父亲的边的权值)。于是把最大边权和变成了最大点权和。
    然后就可以高高兴兴转移了:设节点 (x) 的左儿子是 (l_x) ,右儿子是 (r_x) ,则 (f_{x,i}=max_limits{j in [0,i-1]} { f_{l_x,j}+f_{r_x,i-1-j} } +val_x)
    至于 (l_x)(r_x) 的求法,见下面的 (trick) 吧。

    trick

    一棵给定 (n-1) 条无向边的 (n(n leqslant 3 imes 10^3)) 点有根二叉树左右子节点的求法:
    建立邻接矩阵,只不过这次要存成 (int) 形式, (g_{x,y}) 存的是 ((x,y)) 的边权。
    从根开始建立,自顶向下递归。
    每次递归到当前节点 (x) 时都遍历 (n) 个节点,找到第一个有边权的节点,将其作为 (l_x) ,然后递归处理该节点。返回后直接退出循环即可。找 (r_x) 时注意要重新遍历 (n) 个节点,找到第一个有边权的节点,将其作为 (r_x) ,然后递归处理该节点。

    细节

    注意两个边界: (f_{x,0}) 表示选 (0) 个节点,答案必然为 (0)(l_x=0)(r_x=0) (即 (x) 是个叶节点)时没法选子树,直接返回本身权值即可。

    代码

    $View$ $Code$ ```cpp #include using namespace std; inline int read() { int ret=0,f=1; char ch=getchar(); while('9'
  • 相关阅读:
    【网络安全】十三步简单入侵个人电脑教程
    [深入学习Web安全](11)之XSS玩法
    W3bsafe]SQLmap过狗命令的利用+教程
    Python 爬虫修养-处理动态网页
    WEB站点服务器安全配置
    jboss final 7.1.1相关error以及解决方式
    “System.IO.FileNotFoundException”类型的未经处理的异常在 mscorlib.dll 中发生
    HDU 2196 Computer 树形DP经典题
    python3连接Mairadb数据库
    jQuery动画animate()的使用
  • 原文地址:https://www.cnblogs.com/Peter0701/p/11838826.html
Copyright © 2020-2023  润新知