当前位置 博文首页 > Keven_11的博客:C++题解:奇怪的花卉
????目录
题目?
题解
小明对数学饱有兴趣,并且是个勤奋好学的学生,总是在课后留在教室向老师请教一些问题。一天他早晨骑车去上课,路上见到一个老伯正在修剪花花草草,顿时想到了一个有关修剪花卉的问题。于是当日课后,小明就向老师提出了这个问题:
一株奇怪的花卉,上面共连有?N?朵花,共有?N?1?条枝干将花儿连在一起,并且未修剪时每朵花都不是孤立的。每朵花都有一个“美丽指数”,该数越大说明这朵花越漂亮,也有“美丽指数”为负数的,说明这朵花看着都让人恶心。所谓“修剪”,意为:去掉其中的一条枝条,这样一株花就成了两株,扔掉其中一株。经过一系列“修剪“之后,还剩下最后一株花(也可能是一朵)。老师的任务就是:通过一系列“修剪”(也可以什么“修剪”都不进行),使剩下的那株(那朵)花卉上所有花朵的“美丽指数”之和最大。
老师想了一会儿,给出了正解。小明见问题被轻易攻破,相当不爽,于是又拿来问你。
输入格式
第一行一个整数 N?(1≤N≤16000),表示原始的那株花卉上共?N?朵花。
第二行有?N?个整数,第?i?个整数 ai??(?10^4≤ai?≤10^4)表示第?ii?朵花的美丽指数。
接下来 N?1?行每行两个整数?a,b,表示存在一条连接第?a?朵花和第?b?朵花的枝条。
输出格式
一个数,表示一系列“修剪”之后所能得到的“美丽指数”之和的最大值。
输出时每行末尾的多余空格,不影响答案正确性
要求使用「文件输入输出」的方式解题,输入文件为?
flower.in
,输出文件为?flower.out
样例输入
7 -1 -1 -1 1 1 1 0 1 4 2 5 3 6 4 7 5 7 6 7
样例输出
3
题解:
知识点:树形DP
分析:最基本的树形 dp 问题,任选一个结点作为根进行遍历。dp[u]?表示包含?u?这个节点的子树的美丽指数最大值,遍历?u?的所有儿子?v?后,如果?dp[v]?为正值就加入到当前子树?u?中。此处用链式前向星来存储图,也可用vector,反正都是邻接表
代码:
cs#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int N=32000; int a[N],e[N],ne[N],h[N],idx,dp[N],ans=-0x7fffffff; void init(){//链式前向星 memset(h,-1,sizeof(h)); idx=0; } void add(int x,int y){//链式前向星 e[idx]=y; ne[idx]=h[x]; h[x]=idx++; } int dfs(int u,int fa){//树形DP dp[u]=a[u]; for (int i=h[u];i!=-1;i=ne[i]){ int j=e[i]; if (j!=fa && dfs(j,u)>0){//1.此节点不等于其父节点 2.其子树价值大于0 dp[u]+=dp[j];//不说了,易想 } } ans=max(dp[u],ans);//ans存答案 return dp[u]; } int main(){ freopen("flower.in","r",stdin); freopen("flower.out","w",stdout); init(); int n,x,y; scanf("%d",&n); for (int i=1;i<=n;i++){ scanf("%d",&a[i]); } for (int i=0;i<n-1;i++){ scanf("%d%d",&x,&y); add(x,y); add(y,x); } dfs(1,0); printf("%d",ans); return 0; }
下一篇:没有了