【问题描述】
传说中的九头龙是一种特别贪吃的动物。虽然名字叫“九头龙”,但这只是说它出生的时候有九个头,而在成长的过程中,它有时会长出很多的新头,头的总数会远大于九,当然也会有旧头因衰老而自己脱落。
有一天,有 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. document.write和innerHTML的区别

    document.write是直接写入到页面的内容流,如果在写之前没有调用document.open, 浏览器会自动调用open.每次写完关闭之后重新调用该函数,会导致页面被重写. innerHTML ...

  2. Redis集群知识解析

    redis集群在启动的时候就自动在多个节点间分好片.同时提供了分片之间的可用性:当一部分redis节点故障或网络中断,集群也能继续工作.但是,当大面积的节点故障或网络中断(比如大部分的主节点都不可用了 ...

  3. 27Spring_的事务管理_银行转账业务加上事务控制_基于tx.aop进行声明式事务管理

    上一篇文章中,银行转账业务没有使用事务,会出现问题,所以这篇文章对上篇文章出现的问题进行修改. 事务 依赖 AOP , AOP需要定义切面, 切面由Advice(通知) 和 PointCut(切点) ...

  4. Node.js之Promise

    2015年发布了ES6标准,所谓 Promise,就是ES6标准的一个对象,用来传递异步操作的消息.它代表了某个未来才会知道结果的事件(通常是一个异步操作),并且这个事件提供统一的 API,可供进一步 ...

  5. 【Asp.Net】Asp.Net CommandName作用

    数据绑定控件的模板中 CommandName 属性以下属性值会触发特定的事件: Cancel(取消) Delete(删除) Select(选择) Edit(编辑) Insert(插入) Update( ...

  6. .net 4.0 自定义本地缓存策略的不同实现

    在分布式系统的开发中,为了提高系统运行性能,我们从服务器中获取的数据需要缓存在本地,以便下次使用,而不用从服务器中重复获取,有同学可能要问,为什么不使用 分布式缓存等,注意,服务器端肯定是考虑到扩展, ...

  7. Use CLR Profiler

    Use CLR Profiler 第一次翻译对我而言比较长的E文,有很多不足之处,请见谅.(个人的习惯GC又做了名词又做了名词) 原文:http://msdn.microsoft.com/en-us/ ...

  8. string与stringBuilder的效率与内存占用实测

    using UnityEngine; using System.Diagnostics; using System.Text; using UnityEngine.UI; public class s ...

  9. java从0开始学——数组,一维和多维

    #,在java中,允许数组的长度为0:也就是允许      int[] zeroLenthArray = new int[0]; #,匿名的数组初始化是合法的:     int[] smallPrim ...

  10. [CareerCup] 4.9 All Paths Sum 所有路径和

    4.9 You are given a binary tree in which each node contains a value. Design an algorithm to print al ...