BZOJ5072[Lydsy十月月赛] 小A的树 解题报告【树上背包/树形DP】
来源:互联网 发布:域名备案需要主机吗 编辑:程序博客网 时间:2024/06/16 07:22
Problem Statement
小A 成为了一个园艺家!他有一棵n 个节点的树(如果你不知道树是什么,请看Hint 部分)。他不小心打翻了墨水瓶,使得树的一些节点被染黑了。小A 发现这棵染黑了的树很漂亮,于是想从树中取出一个x 个点的联通子图,使得这些点中恰有y 个黑点,他想知道他的愿望能否实现。可是他太小,不会算,请你帮帮他。
解题报告
这道题可以理解为:有n个点,每个点有其点权,一些点的点权是1,一些点的点权是0,选择每一个点都有代价,代价为1,问能否用大小为x的背包装下权值为y的点。
关于树上背包,有这么一篇博客,这里我们不仅算出最多能选的价值,也算出最小能选到的价值就好了。
具体的状态:
dp[u][j+k]//以u为根节点,一个子树选k个点,其他子树选u个点的最小价值g[u][j+k]//以u为根节点,一个子树选k个点,其他子树选u个点的最大价值
转移:
dp[u][j+k]=min(dp[u][j+k],dp[u][j]+dp[v][k]),g[u][j+k]=max(g[u][j+k],g[u][j]+g[v][k]);
dp数组初值赋+inf,g数组赋0,搜索到每一个点的时候更改dp[u][1]/dp[v][1]。
代码如下:
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int N=5000;struct edge{ int v,next;}ed[2*N+5];int T,n,q;int w[N+5],size[N+5];int dp[N+5][N+5],g[N+5][N+5];int vmax[N+5],vmin[N+5];int head[N+5],num;void build(int u,int v){ ed[++num].v=v; ed[num].next=head[u]; head[u]=num;}void dfs(int u,int f){ size[u]=1; dp[u][1]=w[u],g[u][1]=w[u]; for(int i=head[u];i!=-1;i=ed[i].next) { int v=ed[i].v; if(v==f)continue; dfs(v,u); for(int j=size[u];j;j--) for(int k=0;k<=size[v];k++) dp[u][j+k]=min(dp[u][j+k],dp[u][j]+dp[v][k]), g[u][j+k]=max(g[u][j+k],g[u][j]+g[v][k]); size[u]+=size[v]; } for(int i=1;i<=n;i++)vmin[i]=min(vmin[i],dp[u][i]),vmax[i]=max(vmax[i],g[u][i]);}void init(){ memset(head,-1,sizeof(head));num=0; memset(dp,0x3f,sizeof(dp)); memset(vmin,0x3f,sizeof(vmin)); memset(vmax,0,sizeof(vmax)); memset(g,0,sizeof(g));}int main(){ for(scanf("%d",&T);T;T--) { init(); scanf("%d%d",&n,&q); for(int i=1;i<n;i++) { int u,v; scanf("%d%d",&u,&v); build(u,v); build(v,u); } for(int i=1;i<=n;i++)scanf("%d",&w[i]); dfs(1,0); for(int i=1;i<=q;i++) { int x,y; scanf("%d%d",&x,&y); if(y>=vmin[x]&&y<=vmax[x])printf("YES\n"); else printf("NO\n"); } printf("\n"); } return 0;}
阅读全文
0 0
- BZOJ5072[Lydsy十月月赛] 小A的树 解题报告【树上背包/树形DP】
- bzoj 5072: [Lydsy十月月赛]小A的树 树形dp
- BZOJ 5072: [Lydsy十月月赛]小A的树 树形dp
- BZOJ 5072 [Lydsy 十月月赛] 树DP 解题报告
- BZOJ5071[Lydsy十月月赛] 小A的数字 解题报告
- bzoj5071: [Lydsy十月月赛]小A的数字
- bzoj 5071: [Lydsy十月月赛]小A的数字
- bzoj5071 [Lydsy十月月赛]小A的数字
- bzoj 5071: [Lydsy十月月赛]小A的数字
- BZOJ 5071 [Lydsy 十月月赛] 排序 解题报告
- bzoj 5071: [Lydsy十月月赛]小A的数字 乱搞
- 【乱搞】BZOJ5074 [Lydsy十月月赛]小B的数字
- 【bzoj5074】 [Lydsy十月月赛]小B的数字
- [BZOJ]5074: [Lydsy十月月赛]小B的数字
- bzoj5074 [Lydsy十月月赛]小B的数字
- bzoj 5074: [Lydsy十月月赛]小B的数字
- bzoj 5076: [Lydsy十月月赛]小B的咒语
- bzoj5072 小A的树
- 二叉树的性质
- matlab GUI 新手入门
- react native学习笔记15——Picker、Switch、Slider
- The Summary of October
- 开源负载均衡器DPVS
- BZOJ5072[Lydsy十月月赛] 小A的树 解题报告【树上背包/树形DP】
- session&cookie&网络协议模型
- Java 基础语法
- 基于HSI颜色模型实现去除照片的“红眼现象”
- [HOJ1864]Fibonacci
- C# OpenFileDialog控件
- BZOJ 1475 方格取数【最小割】
- NVIDIA Jetson TK1开发板
- 大写字母转为小写字母