dp优化专辑 I - Cut the Tree [树形dp]
2011-08-19 19:44
513 查看
浙大的题还有有一定的难度的,看了大牛的解题报告才会~ 思路难想,假如想到了写代码是很快的事
![](http://static.blog.csdn.net/xheditor/xheditor_emot/default/wail.gif)
题意:
对一棵树做恰好k次cut操作,每次可以cut一条边,然后丢掉其中一部分而得到一棵新的树。要求最后得到的树的最小和最大权值的和
分析:
比较经典的树形DP模型,其中每个节点对所有儿子又是一个二维DP。DP记录以该节点为根,cut了0 ~ k次所能得到的最小/最大权值。每次有两种选择,一种是保留child,这样update(dp[parent][a + b], dp[parent][a] + dp[child][b])。另一种是直接舍去这棵子树,这样update(dp[parent][a
+ b], dp[parent][a]),其中b可以取1 ~ sizeOfSubtree(j),而不仅仅是1。最后的答案包括两种情况,一种是根在最优解中,那么就是dp[root][k]。否则假设i是最优解中离根最近的点,那么最优解是dp[i][k - j],其中j可以取1 ~ (n – sizeOfSubtree(i)),同样j不仅仅可以取1。
//AC CODE:
![](http://static.blog.csdn.net/xheditor/xheditor_emot/default/wail.gif)
题意:
对一棵树做恰好k次cut操作,每次可以cut一条边,然后丢掉其中一部分而得到一棵新的树。要求最后得到的树的最小和最大权值的和
分析:
比较经典的树形DP模型,其中每个节点对所有儿子又是一个二维DP。DP记录以该节点为根,cut了0 ~ k次所能得到的最小/最大权值。每次有两种选择,一种是保留child,这样update(dp[parent][a + b], dp[parent][a] + dp[child][b])。另一种是直接舍去这棵子树,这样update(dp[parent][a
+ b], dp[parent][a]),其中b可以取1 ~ sizeOfSubtree(j),而不仅仅是1。最后的答案包括两种情况,一种是根在最优解中,那么就是dp[root][k]。否则假设i是最优解中离根最近的点,那么最优解是dp[i][k - j],其中j可以取1 ~ (n – sizeOfSubtree(i)),同样j不仅仅可以取1。
//AC CODE:
#include<iostream> #include<cstring> #include<cstdio> using namespace std; #define INF 9999999 int dp[1010][22];//DP记录以该节点为根,cut了0到m次所能得到的最小或者最大权值 int d[1010];//d[i]表示i结点的出度 int num[1010]; int n,m; int head[1010],cnt; struct node//模拟vector stl里的太龟速了 { int y,next; } a[3030]; void add(int x,int y) { a[cnt].y=y; a[cnt].next=head[x]; head[x]=cnt++; } void dfs(int x,int root) { dp[x][0]=num[x];//初始化x结点 d[x]=0;//初始化x结点 for(int i=1; i<=m; i++)//初始化x结点 dp[x][i]=INF; for(int i=head[x]; i; i=a[i].next) { if(a[i].y==root)//root是i的父节点,不能当作i结点的孩子处理 continue; dfs(a[i].y,x); d[x]+=d[a[i].y]+1;//度数总和(出度)加上与child的这一边,所以 +1 for(int j=m; j>=0; j--) { //1:j刀切在父结点上,直接合并child dp[x][j]+=dp[a[i].y][0]; //2:保持父子关系,自己切k刀,child切j-k刀 for(int k=0; k<j; k++) dp[x][j]=min(dp[x][j],dp[x][k]+dp[a[i].y][j-k]); //3:不要父子关系,可以切1到d[a[i].y]+1刀 父亲和孩子的边也是一刀 +1 for(int k=1; k<=d[a[i].y]+1&&k<=j; k++) dp[x][j]=min(dp[x][j],dp[x][j-k]); } } } int cal() { dfs(1,0);//从结点一开始,0为1的父节点 int ans=dp[1][m]; if(m>0) { for(int i=2; i<=n; i++) for(int j=max(0,m-d[1]+d[i]); j<=d[i]&&j<m; j++)//d[i]保存出度 { ans=min(ans,dp[i][j]); } } return ans; } int main() { int i,x,y; while(scanf("%d%d",&n,&m)!=-1) { cnt=1; memset(head,0,sizeof(head)); for(i=1; i<=n; i++) scanf("%d",&num[i]); for(i=1; i<n; i++) { scanf("%d%d",&x,&y); add(x,y);//图需要建立双向边 add(y,x); } printf("%d ",cal()); for(i=1; i<=n; i++) num[i]=-num[i]; printf("%d\n",-cal()); } }
相关文章推荐
- HDU3848 CC On The Tree, 树形DP
- POJ Cut the Sequence 单调队列优化DP入门题
- poj 3017 Cut the Sequence(dp单调队列优化)
- Codeforces Round #358 (Div. 2) C Alyona and the Tree(树形DP)
- POJ--3017--Cut the Sequence--DP优化
- POJ 3017 Cut the Sequence 【DP+单调队列优化+平衡树】
- hdu5909:Tree Cutting (FWT/点分治优化树形DP)
- dp优化专辑 C - Anniversary party [树形dp]
- hdu 3848 CC on the tree 简单树形dp
- HDU 3848 CC On The Tree(树形dp)
- dp优化专辑 D - Party at Hali-Bula [树形dp]
- POJ-3017 Cut the Sequence(DP单调队列优化 + 平衡树)
- Poj 3017 Cut the Sequence (DP,单调队列优化,数据结构优化)
- dp优化专辑 E - Computer [树形dp]
- dp优化专辑 H -Contestants Division [树形dp]
- [BZOJ4424]CodeForces 19# E Fairy(树形dp / Link-Cut-tree)
- C. Ilya And The Tree(树形搜索+dp)
- poj 3017 Cut the Sequence dp+单调队列优化
- POJ - 3017 Cut the Sequence : 单调队列优化dp
- HDU 4275 Color the Tree(哈希+树同构+组合数学+树形dp)