[Codevs]1746 [NOI2002] 贪吃的九头龙 树形Dp + 多叉转二叉
来源:互联网 发布:树莓派ubuntu系统截图 编辑:程序博客网 时间:2024/05/16 18:29
1746 贪吃的九头龙 2002年NOI全国竞赛
时间限制: 2 s
空间限制: 128000 KB
题目等级 : 大师 Master
题解
题目描述 Description
传说中的九头龙是一种特别贪吃的动物。虽然名字叫“九头龙”,但这只是
说它出生的时候有九个头,而在成长的过程中,它有时会长出很多的新头,头的
总数会远大于九,当然也会有旧头因衰老而自己脱落。
有一天,有M 个脑袋的九头龙看到一棵长有N 个果子的果树,喜出望外,
恨不得一口把它全部吃掉。可是必须照顾到每个头,因此它需要把N 个果子分
成M组,每组至少有一个果子,让每个头吃一组。
这M个脑袋中有一个最大,称为“大头”,是众头之首,它要吃掉恰好K个
果子,而且K个果子中理所当然地应该包括唯一的一个最大的果子。果子由N-1
根树枝连接起来,由于果树是一个整体,因此可以从任意一个果子出发沿着树枝
“走到”任何一个其他的果子。
对于每段树枝,如果它所连接的两个果子需要由不同的头来吃掉,那么两个
头会共同把树枝弄断而把果子分开;如果这两个果子是由同一个头来吃掉,那么
这个头会懒得把它弄断而直接把果子连同树枝一起吃掉。当然,吃树枝并不是很
舒服的,因此每段树枝都有一个吃下去的“难受值”,而九头龙的难受值就是所
有头吃掉的树枝的“难受值”之和。
九头龙希望它的“难受值”尽量小,你能帮它算算吗?
例如图 1 所示的例子中,果树包含8 个果子,7 段树枝,各段树枝的“难受
值”标记在了树枝的旁边。九头龙有两个脑袋,大头需要吃掉4个果子,其中必
须包含最大的果子。即N=8,M=2,K=4:
图一描述了果树的形态,图二描述了最优策略。
大头吃4个果子,用实心点标识;
小头吃4个果子,用空心点标识;
九头龙的难受值为4,因为图中用细边标
记的树枝被大头吃掉了。
输入描述 Input Description
输入文件dragon.in的第1行包含三个整数N (1<=N<=300),M (2<=M<=N),
K (1<=K<=N)。 N 个果子依次编号1,2,…,N,且最大的果子的编号总是1。第2
行到第N行描述了果树的形态,每行包含三个整数a (1<=a<=N),b (1<=b<=N),
c (0<=c<=105),表示存在一段难受值为c的树枝连接果子a和果子b。
输出描述 Output Description
输出文件dragon.out 仅有一行,包含一个整数,表示在满足“大头”的要求
的前提下,九头龙的难受值的最小值。如果无法满足要求,输出-1。
样例输入 Sample Input
8 2 4
1 2 20
1 3 4
1 4 13
2 5 10
2 6 12
3 7 15
3 8 5
样例输出 Sample Output
4
以下是来自同机房oyyl神犇的题解:
注:本题目中所说的最大的果子就是根节点
这道题目应该说是树状dp中比较难的题目了,其中通过树状dp转移时的一些特点,将一棵树从一颗多叉树转化为了二叉树(由于dp状态是通过所有子树状态加和转移,所以同一父亲的兄弟之间的便利顺序就不是特别重要了,而且状态可以累加,所以将一颗多叉树转化为一颗左儿子右兄弟的二叉树也是可以的);
本题目中我们可以先发现一件事情,当有两个即两个以上的小头时,小头便绝对不会吃到树枝:假如我们贪心的在小头没有被选完的情况下,对于下一个果子让没有吃过果子的小头吃果子,那么即能更好的满足让每个小头都吃到果子,有能避免吃树枝的情况,而当所有小头都吃过至少一个果子后,便只需要让父亲与儿子之间不是同一个小头吃的即可,所以可以证明当小头数量大于等于2的时候,小头可以有不吃到树枝的情况。
然而由于题目中又说的是求蓝瘦度最小的情况,那么我们肯定是使小头经量多吃更优,所以我们只让大头刚好吃k个
既然这样,那么当小头数量大于等于2时,本题便至于大头有关了,于是便能容易的想到如何定义状态:
当前结点的状态与两个因素有关:
【1】当前节点是被大头吃还是小头吃
【2】大头在以当前节点为根的子树中吃了多少个果子
那么便很容易写出dp方程:
dp[i][j][0/1] 代表在第i号节点【被吃(1)/ 没被吃(0)】,大头在这颗子树中吃了j个果子;
由于一个节点可能有多个子节点,所以若以多叉树的模式来dp会很恶心(总之我是没写出来的。。。)所以我们可以把它转化为一个二叉树(左儿子右兄弟),由于此题得父亲节点的dp状态是由儿子节点们的dp状态累加起来的,所以可以保证其正确性;
#include<stdio.h>#include<cstring>#include<algorithm>#define deeper(a) memset(a, -1, sizeof(a))using namespace std;const int maxn = 310;const int inf = 1e9;int n, m, k, num;int dp[maxn][maxn][2], h[maxn];struct point{ int ls, rs, w, siz;}p[maxn];struct edge{ int nxt, v, w;}e[maxn * 2];inline void add(int u, int v, int w){ e[++num].v = v, e[num].w = w, e[num].nxt = h[u], h[u] = num; e[++num].v = u, e[num].w = w, e[num].nxt = h[v], h[v] = num;}void dfs_init(int u, int fa){ p[u].siz = 1; for(int i = h[u]; i; i = e[i].nxt){ int v = e[i].v; if(v == fa) continue; dfs_init(v, u); p[u].siz += p[v].siz; p[v].w = e[i].w; p[v].rs = p[u].ls; p[u].ls = v; }}int dfs(int u, int amo, int g){ if(amo < 0) return inf; if(~dp[u][amo][g]) return dp[u][amo][g]; if(!u && !amo) return dp[u][amo][g] = 0; if(!u && amo) return dp[u][amo][g] = inf; dp[u][amo][g] = inf; int lim = min(amo, p[u].siz); for(int i = 0; i <= lim; ++i){ int t1 = dfs(p[u].ls, i - 1, 1) + g * p[u].w; int t2 = dfs(p[u].ls, i, 0) + (m == 2) * (!g) * p[u].w; int t3 = dfs(p[u].rs, amo - i, g); dp[u][amo][g] = min(dp[u][amo][g], min(t1, t2) + t3); } return dp[u][amo][g];}int main(){ deeper(dp); scanf("%d%d%d", &n, &m, &k); for(int i = 1; i < n; ++i){ int a, b, c; scanf("%d%d%d", &a, &b, &c); add(a, b, c); } if(n - k < m - 1) {puts("-1"); return 0;} dfs_init(1, 1); printf("%d\n", dfs(p[1].ls, k - 1, 1));}
- [Codevs]1746 [NOI2002] 贪吃的九头龙 树形Dp + 多叉转二叉
- [codevs1746][NOI2002] 贪吃的九头龙 树形DP
- vijos1523 [NOI2002]贪吃的九头龙(树形dp)
- CodeVs 1746 贪吃的九头龙 (树型dp 多叉转二叉)
- 多叉树转二叉树+树形dp(codevs 1746 贪吃的九头龙 2002noi)
- 【NoI 2002】【CodeVs 1746】【贪吃的九头龙】【树形dp】【记忆化搜索】【多叉树转化二叉树】
- 【NOI2002】贪吃的九头龙
- 贪吃的九头龙-----树形dp
- 【树形dp】贪吃的九头龙
- 【codevs】二叉苹果树 (二叉树的树形dp)
- Vijos 1523 贪吃的九头龙 【树形DP】
- Codevs 1378 选课 树形DP
- [codevs 3639] 树的中心---树形DP(树的重心)
- codevs 1380 没有上司的舞会(树形dp)
- Codevs 1380 没有上司的舞会 [树形dp]
- codevs 1380 没有上司的舞会 树形DP
- 【codevs 1380】没有上司的舞会(树形dp)
- CodeVS 1380 没有上司的舞会(树形DP)
- hdu 3980 Paint Chain(SG函数)
- python基础系列教程——python所有包库的下载
- Haskell语言学习笔记(29)CPS
- Linux11 网络管理
- 【第1082期】关键CSS和Webpack: 减少阻塞渲染的CSS的自动化解决方案
- [Codevs]1746 [NOI2002] 贪吃的九头龙 树形Dp + 多叉转二叉
- 瞄点,路由
- 反作弊工程点滴
- 管理:实务篇序
- 【Java学习3.7.7】三目预算符 结合性 优先级
- 头文件被重复包含有哪些危害?
- [BZOJ]2337: [HNOI2011]XOR和路径 期望+高斯消元
- 学习记录 13-JS DOM操作(17/10/18于成都)
- spark 运行日志