树形DP。

每个点有两个属性:黑色点的权值和,白色点权值和,一个知道另一个也一定知道。

因为只要子树的和它相等的点得权值和不超过x[u],u点的权值总能将其补齐。

设计状态f[u]表示以u为根的子树,和u颜色不同的最小权值和,树形背包转移。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N=1005;
struct Edge{
int to,nxt;
}e[N<<1];
int n,x[N],head[N],ecnt,f[N],g[2][5005];
void add(int bg,int ed){e[++ecnt].nxt=head[bg];e[ecnt].to=ed;head[bg]=ecnt;}
void dfs(int u) {
for(int i=head[u];i;i=e[i].nxt) dfs(e[i].to);
memset(g[0],0x3f,sizeof g[0]);
int cur=0;
g[cur][0]=0;
for(int i=head[u];i;i=e[i].nxt) {
int v=e[i].to;cur^=1;
memset(g[cur],0x3f,sizeof g[cur]);
for(int j=0;j<=x[u];j++) {
if(j-x[v]>=0) g[cur][j]=min(g[cur^1][j-x[v]]+f[v],g[cur][j]);
if(j-f[v]>=0) g[cur][j]=min(g[cur^1][j-f[v]]+x[v],g[cur][j]);
}
}
for(int i=0;i<=x[u];i++) f[u]=min(f[u],g[cur][i]);
}
int main() {
scanf("%d",&n);
for(int i=2,p;i<=n;i++) scanf("%d",&p),add(p,i);
for(int i=1;i<=n;i++) scanf("%d",&x[i]);
memset(f,0x3f,sizeof f);
dfs(1);
if(f[1]<0x3f3f3f3f) puts("POSSIBLE");
else puts("IMPOSSIBLE");
return 0;
}

最新文章

  1. Invoke的使用情景
  2. 再次深入探索datasource问题?
  3. AngularJS语法格式小结
  4. sql数据库带补全终端命令
  5. Xamarin.Android真机调试时闪退解决办法
  6. C辗转相除法求最大公约数的实现
  7. 加入gitignore文件没有起作用怎么办
  8. SAP自带的创建报表工具
  9. Dan计划:重新定义人生的10000个小时 - 阮一峰的网络日志
  10. Nginx stream(TCP/UDP)负载均衡
  11. PHP中静态方法和实例化方法的区别
  12. webpack打包性能优化
  13. Android 里的adb命令
  14. C#工具:汉字转拼音帮助类
  15. HDU2853 Assignment KM
  16. flask 单个页面多个表单(单视图处理、多视图处理)
  17. kbengine学习1 安装
  18. .Net培训班课程体系
  19. windows下一分钟配置ngnix实现HLS m3u8点播
  20. 【LOJ】#2265. 「CTSC2017」最长上升子序列

热门文章

  1. MYSQL存储过程初步认知
  2. Python Django log日志
  3. HelloWorld编译正常运行报noclassdeffounderror
  4. php RSA 简单实现
  5. wifi共享精灵2014.04.25.001已经更新,wifi热点中文名走起!
  6. [React] Reference a node using createRef() in React 16.3
  7. Nginx 做系统的前端反向proxy
  8. Shiro 学习应用(续)
  9. 0x37 容斥原理与莫比乌斯函数
  10. 6.vi使用