博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
luogu P1352 (树形dp)
阅读量:5121 次
发布时间:2019-06-13

本文共 1547 字,大约阅读时间需要 5 分钟。

题意:

给你一棵树,树上的每一个结点都会有一个权值,你可以选取任意多的结点,但是倘若你获取了某个结点\(a_i\),那么他的所有直接儿子就都不会被选取,现在问你最大能够获得的权值。

分析:

树形\(dp\)的入门题目

首先有一个显然的一点,对于每一个结点都会有选和不选两种方案。我们不妨设\(dp[x][0/1]\)。其中\(dp[x][0]\)为以结点\(x\)为根的子树且不选取当前结点\(x\)的权值最大值,\(dp[x][1]\)为以结点\(x\)为根的子树且选取当前结点\(x\)的权值最大值。

那么根据题目的意思,倘若没有选取了\(x\)结点,那么所有显然所有的儿子结点都可以去选取,而每个儿子都会有取和不取两种状态,因此有转移方程\(dp[x][0]+=\sum\max(dp[son[x]][0],dp[son[x]][1])\)

而倘若选取了\(x\)结点,那么显然儿子的所有结点都不能选,故有状态转移方程\(dp[x][1]+=\sum(dp[son][0])\)

最后我们只需要获取一下根结点\(root\)的记录,因为树存在着递归的性质,因此我们只需要通过\(dfs\)从叶子向根进行更新即可,最后的答案为\(\max(dp[root][1],dp[root][0])\)

代码:

#include 
#define maxn 6005using namespace std;struct Node{ int to,next;}q[maxn];int head[maxn],cnt=0,val[maxn],dp[maxn][2],inde[maxn];void add_edge(int from,int to){ q[cnt].to=to; q[cnt].next=head[from]; head[from]=cnt++;}void init(){ memset(head,-1,sizeof(head)); cnt=0;}void dfs(int x){ dp[x][0]=0,dp[x][1]=val[x]; for(int i=head[x];i!=-1;i=q[i].next){ int to=q[i].to; dfs(to); dp[x][0]+=max(dp[to][0],dp[to][1]); dp[x][1]+=dp[to][0]; }}int main(){ int n; scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&val[i]); } int from,to; init(); while(scanf("%d%d",&to,&from)){ if(to==0&&from==0) break; add_edge(from,to); inde[to]++; } int root=0; for(int i=1;i<=n;i++){ if(inde[i]==0){ root=i; break; } } dfs(root); printf("%d\n",max(dp[root][1],dp[root][0])); return 0;}

转载于:https://www.cnblogs.com/Chen-Jr/p/11180518.html

你可能感兴趣的文章
【iOS越狱开发】如何将应用打包成.ipa文件
查看>>
[NOIP2013提高组] CODEVS 3287 火车运输(MST+LCA)
查看>>
Yii2 Lesson - 03 Forms in Yii
查看>>
Python IO模型
查看>>
Ugly Windows
查看>>
DataGridView的行的字体颜色变化
查看>>
Java再学习——关于ConcurrentHashMap
查看>>
如何处理Win10电脑黑屏后出现代码0xc0000225的错误?
查看>>
局域网内手机访问电脑网站注意几点
查看>>
[Serializable]的应用--注册码的生成,加密和验证
查看>>
Day19内容回顾
查看>>
第七次作业
查看>>
SpringBoot项目打包
查看>>
Linux操作系统 和 Windows操作系统 的区别
查看>>
《QQ欢乐斗地主》山寨版
查看>>
文件流的使用以及序列化和反序列化的方法使用
查看>>
Android-多线程AsyncTask
查看>>
第一个Spring冲刺周期团队进展报告
查看>>
红黑树 c++ 实现
查看>>
Android 获取网络链接类型
查看>>