Ural 1018 binary apple tree(显性树的树dp)
2015-05-31 10:30
260 查看
题意:一棵含n个节点的树,保留m条边,使含m条边的子树的边权和最大;
思路:树dp.求含m+1个节点边权和最大的子树。对每个分支节点有三种操作:剪去左子树;剪去右子树;将其节点数合理分配给左右子树;
记以x为根,含k个节点的子树的最大边权和为g[x][k]。
若x为叶节点,则g[x][k]为x通往父节点的边权;若非叶节点,枚举k-1个节点分配在左右子树的所有可能方案,找到最佳方案;
思路:树dp.求含m+1个节点边权和最大的子树。对每个分支节点有三种操作:剪去左子树;剪去右子树;将其节点数合理分配给左右子树;
记以x为根,含k个节点的子树的最大边权和为g[x][k]。
若x为叶节点,则g[x][k]为x通往父节点的边权;若非叶节点,枚举k-1个节点分配在左右子树的所有可能方案,找到最佳方案;
#include<cstdio> #include<cstring> #include<algorithm> #define N 256 #define MAX(a,b) (a>b?a:b) using namespace std; int n,m,ne,x,y,z; //节点数为n,要保留的树枝数为m,边序号为ne,树枝边为(x,y),权为z int id ,w ,v ,next ,head ,lch ,rch ,f ; //第i条边的邻接点为id[i],边权为w[i],后继指针为next[i],节点x的邻接表指针为head[x],二叉树中节点i的左右儿子lch[i],rch[i] //父亲为f[i],通往父节点的边权为v[i] int g ; //状态转移方程 void add(int x,int y,int z) //将边权为z的树枝边(x,y)加入邻接表 { id[++ne]=y; w[ne]=z; next[ne]=head[x]; head[x]=ne; } void dfs(int x) //从节点x出发,构造二叉树 { for(int p=head[x];p;p=next[p]) //搜索x的所有邻接边p if(id[p]!=f[x]) //若边p的邻接点非x的父亲,则作为x的左或右儿子 { if(!lch[x]) lch[x]=id[p]; else rch[x]=id[p]; f[id[p]]=x;v[id[p]]=w[p]; dfs(id[p]); //x作为边p的邻接点的父亲,设定边权,继续递归边p的邻接点 } } int dp(int x,int k) //从x出发,构造含k个节点且能留住最多苹果数的子树 { if(!k) return 0; if(g[x][k]>=0) return g[x][k]; //返回结果 if(!lch[x]) return (g[x][k]=v[x]); //若x为叶子,则返回x通往父节点的边权 for(int i=0;i<k;i++) //计算k个节点分配在左右子树的最佳方案 g[x][k]=MAX(g[x][k],dp(lch[x],i)+dp(rch[x],k-i-1)); g[x][k]+=v[x]; //计入x通往父节点的边权 return g[x][k]; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<n;i++) { scanf("%d%d%d",&x,&y,&z); add(x,y,z); add(y,x,z); //构造邻接表 } dfs(1); //从1出发,构造二叉树 memset(g,255,sizeof(g)); printf("%d\n",dp(1,m+1)); //从节点1出发,计算含m+1个节点且能留住最多苹果数的子树,返回最多苹果数 return 0; }
相关文章推荐
- Android CTS 测试总结【转】
- App installation failed There was an internal API error.
- Android学习之路—新手学Android的体会!
- Android客户端请求服务器端的详细解释(附源代码)
- 【Android】线程及异步操作
- Android中的ListView使用案例(SimpleAdapter实现)
- Android动画原理分析
- Android 手写签名和裁剪
- Android中Activity启动过程探究
- mac xcode6.4 使用 cocos2dx-2.x cocos2dx-3.x 环境配置建立工程
- Android使用ViewFlipper实现左右滑动效果面
- android好用模拟器genymotion安装过程
- Object-C中内存引用计数
- Android View 绘制流程
- Android中实现滑动翻页—使用ViewFlipper
- iOS 判断设备是否越狱
- Cordova webapp实战开发:(3)后面可能会学到的东西
- 使用 ARChon 运行时环境在 Ubuntu 上运行 Android 应用
- Android TextView里直接显示图片的三种方法
- 【Android】工程中文件的关联性