【问题描述】
传说中的九头龙是一种特别贪吃的动物。虽然名字叫“九头龙”,但这只是说它出生的时候有九个头,而在成长的过程中,它有时会长出很多的新头,头的总数会远大于九,当然也会有旧头因衰老而自己脱落。
有一天,有 M 个脑袋的九头龙看到一棵长有 N 个果子的果树,喜出望外,恨不得一口把它全部吃掉。可是必须照顾到每个头,因此它需要把 N 个果子分成 M 组,每组至少有一个果子,让每个头吃一组。
这 M 个脑袋中有一个最大,称为“大头”,是众头之首, 它要吃掉恰好 K 个果子,而且 K 个果子中理所当然地应该包括唯一的一个最大的果子。 果子由 N-1根树枝连接起来,由于果树是一个整体,因此可以从任意一个果子出发沿着树枝“走到”任何一个其他的果子。
对于每段树枝,如果它所连接的两个果子需要由不同的头来吃掉,那么两个头会共同把树枝弄断而把果子分开;如果这两个果子是由同一个头来吃掉,那么这个头会懒得把它弄断而直接把果子连同树枝一起吃掉。当然,吃树枝并不是很舒服的,因此每段树枝都有一个吃下去的“难受值”,而九头龙的难受值就是所有头吃掉的树枝的“难受值”之和。
九头龙希望它的“难受值”尽量小,你能帮它算算吗?
例如图 1 所示的例子中,果树包含 8 个果子,7 段树枝,各段树枝的“难受值”标记在了树枝的旁边。九头龙有两个脑袋,大头需要吃掉 4 个果子,其中必须包含最大的果子。即 N=8,M=2,K=4:
最大的果子大头吃 4 个果子,用实心点标识;小头吃 4 个果子,用空心点标识;九头龙的难受值为 4,因为图中用细边标记的树枝被大头吃掉了。
【输入文件】
输入文件 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<=10 5 ),表示存在一段难受值为 c 的树枝连接果子 a 和果子 b。
【输出文件】
输出文件 dragon.out 仅有一行,包含一个整数,表示在满足“大头”的要求的前提下,九头龙的难受值的最小值。如果无法满足要求,输出-1。
【样例输入】
8 2 4
1 2 20
1 3 4
1 4 13
2 5 10
2 6 12
3 7 15
3 8 5
【样例输出】
4
【样例说明】
该样例对应于题目描述中的例子。

正解:树形DP

解题报告:

  今天考试T4,居然是NOI原题。

  显然是一道树形DP,但是我们考虑记录的状态是什么:f[0、1][i][j]表示以i为根结点的子树中1号吃了j个并且i不选或者选的最小值。同时记忆化。

  直接分类讨论儿子结点选了多少个,总复杂度O(N^3)。

  代码如下:

 //It is made by jump~
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <ctime>
#include <vector>
#include <queue>
#include <map>
#include <set>
using namespace std;
typedef long long LL;
const int MAXN = ;
LL inf;
int n,m,k,ecnt;
int first[MAXN],next[MAXN*],to[MAXN*];
int brother[MAXN],son[MAXN],lian[MAXN][MAXN];
bool vis[MAXN];
LL f[][MAXN][MAXN]; inline int getint()
{
int w=,q=; char c=getchar();
while((c<'' || c>'') && c!='-') c=getchar(); if(c=='-') q=,c=getchar();
while (c>='' && c<='') w=w*+c-'', c=getchar(); return q ? -w : w;
} inline void down(int x,int fa){
vis[x]=;
for(int i=first[x];i;i=next[i]) {
int v=to[i]; if(vis[v]) continue;
//printf("%d %d\n",v,brother[v]);
brother[v]=son[x]; son[x]=v; down(v,x);
}
} inline LL dfs(int x,int fa,int remain,int flag){
if(x==) { if(remain==) return ; else return -; }
if(f[flag][x][remain]!=-) return f[flag][x][remain];
LL minl=inf,nowl,nowr,suan;
for(int i=;i<=remain;i++) {
nowl=dfs(brother[x],fa,i,flag);
if(nowl==remain) nowr=-;
else nowr=dfs(son[x],x,remain-i-,);//选 /*if(nowl>=0) {
if(flag==1) { suan=nowl+nowr+lian[fa][x]; } else suan=nowl+nowr;
if(suan<minl) minl=suan; }
*/ if(nowl>= && nowr>=) {
if(flag==) { suan=nowl+nowr+lian[fa][x]; } else suan=nowl+nowr;
minl=min(minl,suan);
}
nowr=dfs(son[x],x,remain-i,);//不选
/*if(nowl>=0) {
if(flag==0 && m==2) suan=nowl+nowr+lian[fa][x]; else suan=nowl+nowr;
minl=min(minl,suan);
}*/
if(nowl>= && nowr>=) {
if(flag== && m==) suan=nowl+nowr+lian[fa][x]; else suan=nowl+nowr;
minl=min(minl,suan);
}
}
//printf("%d %d %d %d\n",x,fa,remain,flag);
if(minl==inf) f[flag][x][remain]=-inf; else f[flag][x][remain]=minl;
return f[flag][x][remain];
} inline void work(){
n=getint(); m=getint(); k=getint(); inf=; for(int i=;i<=;i++) inf*=;
int x,y,z;
for(int i=;i<n;i++) {
x=getint(); y=getint(); z=getint(); lian[x][y]=lian[y][x]=z;
next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y;
next[++ecnt]=first[y]; first[y]=ecnt; to[ecnt]=x;
}
if(m-+k>n) { printf("-1"); return ; }
down(,); memset(f,-,sizeof(f));
dfs(son[],,k-,);
printf("%lld",f[][son[]][k-]);
} int main()
{
work();
return ;
}

codevs1746 贪吃的九头龙的更多相关文章

  1. [codevs1746][NOI2002]贪吃的九头龙

    [codevs1746][NOI2002]贪吃的九头龙 试题描述 传说中的九头龙是一种特别贪吃的动物.虽然名字叫"九头龙",但这只是说它出生的时候有九个头,而在成长的过程中,它有时 ...

  2. Vijos1523贪吃的九头龙【树形DP】

    贪吃的九头龙 传说中的九头龙是一种特别贪吃的动物.虽然名字叫"九头龙",但这只是说它出生的时候有九个头,而在成长的过程中,它有时会长出很多的新头,头的总数会远大于九,当然也会有旧头 ...

  3. 贪吃的九头龙(tyvj P1523)

    T2 .tyvj   P1523贪吃的九头龙 描述 传说中的九头龙是一种特别贪吃的动物.虽然名字叫“九头龙”,但这只是说它出生的时候有九个头,而在成长的过程中,它有时会长出很多的新头,头的总数会远大于 ...

  4. Vijos 1523 贪吃的九头龙 【树形DP】

    贪吃的九头龙 背景 安徽省芜湖市第二十七中学测试题 NOI 2002 贪吃的九头龙(dragon) Description:OfficialData:OfficialProgram:Converted ...

  5. [NOI2002]贪吃的九头龙(树形dp)

    [NOI2002]贪吃的九头龙 题目背景 传说中的九头龙是一种特别贪吃的动物.虽然名字叫"九头龙",但这只是 说它出生的时候有九个头,而在成长的过程中,它有时会长出很多的新头,头的 ...

  6. vojis1523 NOI2002 贪吃的九头龙

    描述 传说中的九头龙是一种特别贪吃的动物.虽然名字叫“九头龙”,但这只是说它出生的时候有九个头,而在成长的过程中,它有时会长出很多的新头,头的总数会远大于九,当然也会有旧头因衰老而自己脱落. 有一天, ...

  7. codevs贪吃的九头龙

    传说中的九头龙是一种特别贪吃的动物.虽然名字叫“九头龙”,但这只是说它出生的时候有九个头,而在成长的过程中,它有时会长出很多的新头,头的总数会远大于九,当然也会有旧头因衰老而自己脱落.有一天,有M 个 ...

  8. [NOI2002] 贪吃的九头龙

    题目类型:树形DP 传送门:>Here< 题意:有一只九头龙要吃了一颗树,给出一棵\(N\)个节点的带边权的树.九头龙有\(M\)个头,其中一个是大头,大头要吃恰好\(K\)个节点,其他头 ...

  9. Vijos1523 NOI2002 贪吃的九头龙 树形dp

    思路不算很难,但细节处理很麻烦 前面建图.多叉转二叉,以及确定dp处理序列的过程都是套路,dp的状态转移过程以注释的形式阐述 #include <cstdio> #include < ...

随机推荐

  1. AC日记——阶乘之和 洛谷 P1009(高精度)

    题目描述 用高精度计算出S=1!+2!+3!+…+n!(n≤50) 其中“!”表示阶乘,例如:5!=5*4*3*2*1. 输入输出格式 输入格式: 一个正整数N. 输出格式: 一个正整数S,表示计算结 ...

  2. Beaufort密码

    博福特密码,是一种类似于维吉尼亚密码的替代密码,由弗朗西斯·蒲福(Francis Beaufort)发明.它最知名的应用是M-209密码机.博福特密码属于对等加密,即加密演算法与解密演算法相同 博福特 ...

  3. 07SpringMvc_jsp到jsp的控制器_ParameterizableViewController

    本文主要讲的是控制器,Action继承什么类.记得Springmvc系列的第一篇文章说过.SpirngMVC的实现流程.

  4. 千份位Javascript Thousand Separator / string format

    function Separator(str){ return str.split(/(\d+)(\d{3})(\d{3})(\d{3})(\d{3})/).join(',').replace(/^, ...

  5. 蒙古人交友网站 www.mengguren.com

    蒙古人交友http://www.mengguren.com/ 经过一个多月的努力,终于上线了,虽然长得丑陋一些.功能简单一些,欢迎大家注册,方便别人能找到您.吉日嘎拉<252056973@qq. ...

  6. MySQL基础 - 注意事项

    AND比OR优先级高,故在同时使用AND和OR进行查找时记得加上小括号,当同时存在多个条件时统一加上括号是个好习惯. NULL不参与搜索,即使使用LIKE '%'也匹配不到值为NULL的记录. LIK ...

  7. 去他的效应(what-the-hell effect)与自我放纵

    去他的 效应(what-the-hell effect)与自我放纵 为什么写这篇文章: 对于我来说,但我感到疲惫——"无意拿起"手机,对自己说"随便看看"——但 ...

  8. 解决 Windows Update 时提示当前无法检查更新,因为未运行服务

    故障:打开“Windows Update”出现红色盾牌图标 点击“检查更新”,出现“Windows Update 当前无法检查更新,因为未运行服务.您可能需要重新启动计算机” 查看“Windows U ...

  9. &10 基本数据结构——指针和对象的实现,有根树的表示

    #1,指针和对象的实现 如果所用的语言或者环境不支持指针和对象,那我们该怎么用数组来将其转化呢?实质上可以将这个问题的本质转化为数组和链表这两种数据结构的转换,准确来说,是将链表表示的数据用数组表示. ...

  10. Android 获取手机Mac地址,手机名称

    /** * 获取手机mac地址<br/> * 错误返回12个0 */ public static String getMacAddress(Context context) { // 获取 ...