一、题目

二、解题思路

  1. 对于该题,我首先把它当成了图的问题,结果没找到突破口。后来看到题目:最大子树和以及关键字:未修建时每朵花不孤立、N个节点N-1条边,意味着这是一颗最小生成树,于是选择将该问题当成树的问题。

  2. 既然是树的问题,那么意味着我们需要找到树的根节点。接着想到,对于美丽指数为负数的节点,必不可能为根节点,原因见下图:

    图中白色数值表示节点美丽指数,黑色数值表示节点编号。左图描述了节点1不需要保留的情况,右边图描述了节点1需要保留的情况。对于左图,节点1不需要保留,那必然不能作为根节点,因为作为根节点意味着该节点一定会被保留;对于右图,虽然节点1需要保留,但是它与节点2和节点3作为根节点时的情况重复,因此也不需要作为根节点进行讨论。综上,负数节点不可能作为根节点。

  3. 那不妨先任意找一个美丽指数为正数的节点作为根节点。以题目给的样例为例,进行分析,当以节点4为根节点时,树的情况见下图:

    树的结构一画出,就可以看出问题其实很容易求解。显然,叶子节点是否保留是最容易确认的,当叶子节点为负数时,必然需要修剪掉,当为正数时,必然需要保留;紧接着,与叶子节点相连的节点是否需要保留同样就可以确定。即对于图中描述的情况,节点1和节点7是否保留,只需要看以节点1和节点7为根节点的子树的最大美丽指数是否大于0即可,如果大于0,那么需要保留,小于0,那么修剪即可。不难看出,这个过程明显是递归过程,因为当子节点的情况确定后,父节点的情况就会相应确定。

  4. 刚才的分析,我们是任意选择了一个美丽指数为正数的节点作为根节点, 那么需要分析,当根节点不同时,结果是否不同,如果相同,只需要随便选一个节点作为根节点即可,但如果不同,则需要逐个遍历。看下图所示情况:

    此时,最优值为1。但是,很容易看出,如果我们以节点5为根节点,最优值为7。所以,我们需要进行逐个遍历。值得注意的是,部分结果是可以重复利用的,比如当根节点为4时,对于子节点7来说,当它为根节点时,根节点为5的子树的最大美丽指数情况已经确定,那么当根节点为7时,子节点为5的最大美丽指数情况实际上已经不需要再重新计算(当把树看做有向图时,该性质会更容易理解)。

  5. 当你以为已经结束时,实际上还未结束。因为有一种情况被忽视:所有节点的美丽指数均为负数。实际上,该种情况很容易解决,只需要保留美丽指数最大的那个节点就够了,其他的都修剪掉。

三、代码

#include<iostream>
#include<string>
#include<vector>
#include<map>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
int ret=0, max_beauty=0, min_negtive=1, N;
vector<vector<int>> adj(16001, vector<int>()),child_beauty(16001, vector<int>());
vector<int> positive_node,beauty(16001);//计算当根节点为parent时,它的子树(以adj[parent][node_index]为根节点)的最大美丽指数
void search_child_beauty(int parent, int node_index){if(child_beauty[parent][node_index]!=-1)return;int now_node=adj[parent][node_index];int now_beauty=beauty[now_node];for(int i=0;i<child_beauty[now_node].size();i++){if(adj[now_node][i]==parent)continue;//由于子树的最大美丽指数必然为非负数,所以当为负数时,那一定未计算过if(child_beauty[now_node][i]==-1)search_child_beauty(now_node, i);now_beauty+=child_beauty[now_node][i];}//最大美丽指数一定是非负数,因为如果子树的最大美丽指数为负数时,我们可以直接将整棵子树修建掉if(now_beauty>0)child_beauty[parent][node_index]=now_beauty;elsechild_beauty[parent][node_index]=0;
}int main(){cin>>N;for(int i=1;i<=N;i++){cin>>beauty[i];ret+=beauty[i];if(beauty[i]>=0){//美丽指数为负数的节点,不可能当树的根节点,具体原因可自己画图理解positive_node.push_back(i);//记录一下最大可能值,方便提早结束遍历。如果某次修剪能把所有的负数花朵去掉,那必然是最优结果max_beauty+=beauty[i];}if(min_negtive>0||beauty[i]>min_negtive)min_negtive=beauty[i];}//构建邻接表以及初始化每个节点子树的最大美丽指数for(int i=1;i<N;i++){int a,b;cin>>a>>b;adj[a].push_back(b);child_beauty[a].push_back(-1);adj[b].push_back(a);child_beauty[b].push_back(-1);}//遍历,当节点positive_node[i]作为根节点时,该树对应的最大美丽指数for(int i=0;i<positive_node.size();i++){int now_node=positive_node[i];int now_beauty=beauty[now_node];for(int j=0;j<adj[now_node].size();j++){if(child_beauty[now_node][j]==-1)search_child_beauty(now_node, j);now_beauty+=child_beauty[now_node][j];}if(now_beauty>ret)ret=now_beauty;if(ret==max_beauty)break;}if(positive_node.size()==0)cout<<min_negtive;else cout<<ret;
}

P1122 最大子树和相关推荐

  1. 洛谷 P1122 最大子树和 题解

    题目:P1122 最大子树和 DP - 树形DP - dfs 这题的做法被题目名字给暴露了 设 f [ i ] f[i] f[i] 为以点 i i i 为根的子树中的最大子树和 设 j j j 为 i ...

  2. 洛谷P1122 最大子树和 树形DP初步

    小明对数学饱有兴趣,并且是个勤奋好学的学生,总是在课后留在教室向老师请教一些问题.一天他早晨骑车去上课,路上见到一个老伯正在修剪花花草草,顿时想到了一个有关修剪花卉的问题.于是当日课后,小明就向老师提 ...

  3. 洛谷 P1122 最大子树和-求树的最大子树权值和

    输入: 7 -1 -1 -1 1 1 1 0 1 4 2 5 3 6 4 7 5 7 6 7 输出: 3 代码如下: #include <iostream> #include <ve ...

  4. Luogu P1122 最大子树和 树形DP

    题目描述 小明对数学饱有兴趣,并且是个勤奋好学的学生,总是在课后留在教室向老师请教一些问题.一天他早晨骑车去上课,路上见到一个老伯正在修剪花花草草,顿时想到了一个有关修剪花卉的问题.于是当日课后,小明 ...

  5. 洛谷P1122最大子树和题解

    题目 一道比较好想的树形\(DP\) 完全可以用树形DP的基本思路,递归,然后取最优的方法. \(Code\) #include <iostream> #include <cstri ...

  6. 树形dp瞎讲+树形dp基础题题解

    ---恢复内容开始--- 没错 咕了这么久(没有青青姐久 我又开始写博客了( ´▽`) 想了很久些什么(才没有想过呢 虽然被鄙视基础不好但还是走上了树形dp的不归路 那么 就来写写树形dp吧(dtx ...

  7. 2019.2-2019.3 TO-DO LIST

    DP P2723 丑数 Humble Numbers(完成时间:2019.3.1) P2725 邮票 Stamps(完成时间:2019.3.1) P1021 邮票面值设计(完成时间:2019.3.1) ...

  8. 最大子树和(洛谷-P1122)

    题目描述 小明对数学饱有兴趣,并且是个勤奋好学的学生,总是在课后留在教室向老师请教一些问题.一天他早晨骑车去上课,路上见到一个老伯正在修剪花花草草,顿时想到了一个有关修剪花卉的问题.于是当日课后,小明 ...

  9. 判定两棵二叉树是否相似以及左右子树交换、层次编号

    #include <iostream> using namespace std; #include <malloc.h> #include <stdio.h> #d ...

最新文章

  1. 实时可视化 Debug:VS Code 开源新工具,一键解析代码结构
  2. (转)在Windows上安装GPU版Tensorflow
  3. java spring注解维护,从一次工程启动失败谈谈 spring 注解
  4. 2021年B站创作者生态报告
  5. pb 查询客户端ip地址_特别篇-SAP 客户端(配置、测试、生产)
  6. ”扶我起来,我还能学!“ 之ES2021 抢先尝
  7. ORACLE数据库维护
  8. win10开移动热点让手机使用上网
  9. java 自动装载_JAVA反射技术之自动装载/自动验参
  10. CSDN上传的资源为何不能自定义下载积分?
  11. 百度网站打不开了,只有百度首页跟搜索页打不开其它能正常打开怎么解决?
  12. 六爪机器人_六爪机器人
  13. 学习:C# 中的委托和事件(转)
  14. 编写可变参数函数 c语言,C语言可变参数函数的编写
  15. Psim仿真_pi输出加限幅(疑惑)
  16. Unity3d使用RenderTexture制作动态头像
  17. android 为什么不调用onDestroy方法关闭activity
  18. 西瓜卡顿 ANR 优化治理及监控体系建设
  19. VR全景拍摄怎么设置相机
  20. 积木Sketch Plugin:设计同学的贴心搭档

热门文章

  1. 如何固定Excel的表头和列(滚动时始终显示表头和首列)
  2. 蓝桥杯2017 B组C省赛真题 2017-10 k倍区间
  3. eclipse发展与简介
  4. 图像处理一大神器:图像去噪
  5. 小黑抱紧沛奇老师课程的大腿,继续学习git的日常积累:沛奇老师git笔记(git命令与分支)
  6. 神经外科病人资料管理系统
  7. maven的下载安装与卸载
  8. Python | 判定IP地址合法性的四种方法
  9. Python内置函数(知识总结篇)
  10. C# 2.0 泛型编程