bzoj 2645: Vijos1676 陶陶吃苹果 (树形DP)
2017-05-24 20:00
218 查看
题目描述
传送门
题目大意:一棵苹果树有n个节点,每个节点上有c[i]个苹果,这棵树高度为h。剪掉一些枝条,使得修剪过后的树满足节点数-高度≤k,且保留尽可能多的苹果。
题解
如果一个点被保留,那么这个点到根路径上的点都会被保留。那么这就满足树形依赖问题。解决树形依赖问题的常见做法就是将父节点的值给当前节点,然后用当前节点继续深层的计算。
f[son]=f[x],然后用递归后的f[son]更新f[x]
f[x][i]=max(f[son][i−1]+a[son],f[x][i]),可以发现如果这么计算的话,我们实际上加入的是这个点到根链左侧所以节点的最优贡献。
考虑这道题,t-h<=k的限制实际上就是白送了你一条链,那么我们可以对于每一条链预处理出链的左右两侧的贡献,然后枚举所有叶子节点到根的路径,计算答案即可。
代码
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #define N 4003 using namespace std; int fl [503],fr [503],a ; int v ,du ,n,m,sum ; void dfsl(int x) { for (int i=1;i<=du[x];i++) { int now=v[x][i]; sum[now]=sum[x]+a[now]; for (int j=0;j<=m;j++) fl[now][j]=fl[x][j]; dfsl(now); for (int j=1;j<=m;j++) fl[x][j]=max(fl[x][j],fl[now][j-1]+a[now]); } } void dfsr(int x) { for (int i=du[x];i>=1;i--) { int now=v[x][i]; for (int j=0;j<=m;j++) fr[now][j]=fr[x][j]; dfsr(now); for (int j=1;j<=m;j++) fr[x][j]=max(fr[x][j],fr[now][j-1]+a[now]); } } int main() { freopen("a.in","r",stdin); scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) { int x; scanf("%d%d",&x,&a[i]); v[x][++du[x]]=i; } sum[1]=a[1]; dfsl(1); dfsr(1); int ans=0; for (int i=1;i<=n;i++) if(du[i]==0){ for (int j=0;j<=m;j++) ans=max(ans,fl[i][j]+fr[i][m-j]+sum[i]); } printf("%d\n",ans); }
相关文章推荐
- BZOJ 2645 陶陶吃苹果 [树形DP]
- [Vijos 1676] 陶陶吃苹果
- 树形背包DP的两种优化方式——vijos1676、codeforces815c
- BZOJ4557 JLOI2016侦察守卫(树形dp)
- BZOJ 1131 POI2008 Sta 树形DP
- 【BZOJ2427】【HAOI2010】软件安装 tarjan+树形背包DP
- BZOJ 3566: [SHOI2014]概率充电器 期望DP + 树形DP
- bzoj 3037(树形DP)
- bzoj 4033: [HAOI2015]树上染色 [树形DP]
- 【BZOJ】2060: [Usaco2010 Nov]Visiting Cows 拜访奶牛(树形dp)
- 【BZOJ 1060】 1060: [ZJOI2007]时态同步 (树形DP)
- BZOJ 1060: [ZJOI2007]时态同步( 树形dp )
- bzoj4033 T1 树形dp
- bzoj1864 三色二叉树 树形dp
- [bzoj4033][HAOI2015]树上染色_树形dp
- BZOJ 2152: 聪聪可可【树形dp
- bzoj 1040: [ZJOI2008]骑士【基环树+树形dp】
- 2015湖南省赛A题 BZOJ4254 Aerial Tramway 树形dp
- bzoj 1060: [ZJOI2007]时态同步【树形dp】
- bzoj 2435: [Noi2011]道路修建【树形dp】