URAL 1018 Binary Apple Tree 树形DP 好题 经典
2015-06-01 14:55
459 查看
1018. Binary Apple Tree
Time limit: 1.0 secondMemory limit: 64 MB
Let's imagine how apple tree looks in binary computer world. You're right, it looks just like a binary tree, i.e. any biparous branch splits up to exactly two new branches. We will enumerate by integers the root of binary apple tree, points of branching and the ends of twigs. This way we may distinguish different branches by their ending points. We will assume that root of tree always is numbered by 1 and all numbers used for enumerating are numbered in range from 1 to N, where N is the total number of all enumerated points. For instance in the picture below N is equal to 5. Here is an example of an enumerated tree with four branches:
2 5 \ / 3 4 \ / 1 |
Input
First line of input contains two numbers: N and Q (2 ≤ N ≤ 100; 1 ≤ Q ≤ N − 1). N denotes the number of enumerated points in a tree. Q denotes amount of branches that should be preserved. NextN − 1 lines contains descriptions of branches. Each description consists of a three integer numbers divided by spaces. The first two of them define branch by it's ending points. The third number defines the number of apples on this branch. You may assume that no branch contains more than 30000 apples.Output
Output should contain the only number — amount of apples that can be preserved. And don't forget to preserve tree's root ;-)Sample
input | output |
---|---|
5 2 1 3 1 1 4 10 2 3 20 3 5 20 | 21 |
某一位大神说,经典题都要自己做,不能看题解,因为做一题少一题
这道题从昨晚11点到1点,然后今天12:30继续想到2:00,终于AC了,挺开心的。
题意:给出一颗二叉树,有n个节点,编号为1~n,1是根节点。
树上的每一条边挂有一些苹果(为什么不是在节点挂苹果),然后问你只保留k条边的情况下,最多能保留多少个苹果。
昨晚想的是用优先队列,知道了保留的边数,就知道了要去掉的边数。递归处理树,把每一条边的权值放到2个节点中深度较大的那一个节点,然后递归处理,每一个节点的权值变为以这个节点为根的子树的权值的和,包括本身的权值。
然后每次把叶子节点放入优先队列中,每输出一个节点,要去掉的边就-1,然后把这个节点的父亲节点的权值更新后加入优先队列。直到要去掉的边为0.
然而,这样是错的。
无法保证最优。
乖乖树形DP.
dp[i][j]表示以i为根的子树保留j个顶点时的最大的苹果树。
然后递归处理后,自底向上递归求解。
分别考虑没有子树,只有左子树,左右子树都有的情况。
注意:根据处理,有右子树就一定有左子树。
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=110; int dp[maxn][maxn]; int ls[maxn]; int rs[maxn]; int w[maxn]; //节点的权值 int siz[maxn]; //以之为根的子树的节点个数 int dep[maxn]; int e[maxn][3]; //保存2个节点和权值 struct Edge { int to,next; }edge[maxn<<1]; int head[maxn]; int tot; int n,k; void init() { memset(head,-1,sizeof(head)); tot=1; memset(ls,-1,sizeof(ls)); memset(rs,-1,sizeof(rs)); memset(dep,-1,sizeof(dep)); memset(siz,0,sizeof(siz)); memset(dp,-1,sizeof(dp)); } void addedge(int u,int v) { edge[tot].to=v; edge[tot].next=head[u]; head[u]=tot++; } void dfs1(int u,int d) { siz[u]=1; dep[u]=d; for(int i=head[u];~i;i=edge[i].next) { int v=edge[i].to; if(dep[v]<0) { dfs1(v,d+1); siz[u]+=siz[v]; } } } void dfs2(int u) { if(siz[u]<=1) return ; for(int i=head[u];~i;i=edge[i].next) { int v=edge[i].to; if(dep[v]<dep[u]) continue; if(ls[u]==-1) { ls[u]=v; dfs2(v); } else { rs[u]=v; dfs2(v); } } } void tree_dp(int u) { if(ls[u]==-1&&rs[u]==-1) { dp[u][0]=0; dp[u][1]=w[u]; } else if(ls[u]!=-1&&rs[u]==-1) { dp[u][0]=0; tree_dp(ls[u]); for(int j=1;j<=siz[u];j++) { for(int k=0;k<=siz[ls[u]];k++) { dp[u][j]=max(dp[u][j],dp[ls[u]][j-1]+w[u]); } } } else { dp[u][0]=0; tree_dp(ls[u]); tree_dp(rs[u]); for(int j=1;j<=siz[u];j++) { for(int k=0;k<=siz[ls[u]];k++) { int tmp=j-k-1; if(tmp>=0&&tmp<=siz[rs[u]]) { dp[u][j]=max(dp[u][j],dp[ls[u]][k]+dp[rs[u]][tmp]+w[u]); } } } } } int main() { while(scanf("%d%d",&n,&k)!=EOF) { init(); for(int i=1;i<n;i++) { scanf("%d%d%d",&e[i][0],&e[i][1],&e[i][2]); addedge(e[i][0],e[i][1]); addedge(e[i][1],e[i][0]); } if(k>n-1) { k=n-1; //注意这里 } dfs1(1,1); //求出siz,dep //给深度大的节点加上权值 for(int i=1;i<n;i++) { if(dep[e[i][0]]>dep[e[i][1]]) swap(e[i][0],e[i][1]); w[e[i][1]]=e[i][2]; } dfs2(1); //求出左二子和右儿子 tree_dp(1); printf("%d\n",dp[1][k+1]); //保留k条边就有k+1个节点 } return 0; }
View Code
相关文章推荐
- 【Android笔记】Android引用第三方依赖包library报错解决方法
- Untiy assets报错找不到资源在guidmapper
- 苹果开发小记(一):NSString 的比较用法
- Android Activity组件正常以及锁屏状态下的启动流程
- Swift的属性,方法,下标脚本以及继承
- ImageView android:tint
- 发现数据库错误模式(AppScan扫描结果)
- 放大招了!基于Bmob的Android即时通讯应用源码[升级版]
- Android性能优化典范(二)
- Android性能优化典范
- iOS shareSDK进行分享
- Android 应用性能优化(一)JAVA代码优化
- 链接注入(便于跨站请求伪造)(AppScan扫描结果)
- 安卓自定义日期控件(仿QQ,IOS7)续
- 安卓自定义日期控件(仿QQ,IOS7)续
- 利用思维导图来规划APP开发
- unity 全屏乱影 BlitMultiTap
- Android之NDK开发
- iOS人脸识别(检测)
- Unity3d Asset Serialization 设置错误导致SVN文件不能同步