[NOI2002]贪吃的九头龙

题目背景

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

题目描述

有一天,有 M 个脑袋的九头龙看到一棵长有 N 个果子的果树,喜出望外, 恨不得一口把它全部吃掉。可是必须照顾到每个头,因此它需要把 N 个果子分成 M 组,每组至少有一个果子,让每个头吃一组。

这M个脑袋中有一个最大,称为“大头”,是众头之首,它要吃掉恰好 K 个 果子 ,而 且 K 个果子中理所当然地应该包括唯一的一个 最大的果子。 果子由 N-1 根树枝连接起来,由于果树是一个整体,因此可以从任意一个果子出发沿着树枝 “走到”任何一个其他的果子。

对于每段树枝,如果它所连接的两个果子需要由不同的头来吃掉,那么两个 头会共同把树枝弄断而把果子分开;如果这两个果子是由同一个头来吃掉,那么 这个头会懒得把它弄断而直接把果子连同树枝一起吃掉。当然,吃树枝并不是很舒服的,因此每段树枝都有一个吃下去的“难受值”,而九头龙的难受值就是所 有头吃掉的树枝的“难受值”之和。

九头龙希望它的“难受值”尽量小,你能帮它算算吗?

例如图 1 所示的例子中,果树包含 8 个果子,7 段树枝,各段树枝的“难受 值”标记在了树枝的旁边。九头龙有两个脑袋,大头需要吃掉 4 个果子,其中必 须包含最大的果子。即 N=8,M=2,K=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^5105),表示存在一段难受值为 c 的树枝连接果子 a 和果子 b。

输出格式:

输出文件 dragon.out 仅有一行,包含一个整数,表示在满足“大头”的要求 的前提下,九头龙的难受值的最小值。如果无法满足要求,输出-1。

输入输出样例

输入样例#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

输出样例#1: 复制

4

说明

该样例对应于题目描述中的例子。

题解

一眼树形dp。
首先按照套路想了一下
\(dp[i][j][k]\)表示第\(i\)个节点,给第\(j\)个头,第\(j\)个头已有\(k\)个果子。
然而我们并不能确定第\(j\)个头的果子在哪里。
不好记录一条边连接的两端归哪个头。
且空间会炸起飞。
那么我们换一种套路。

\(f[i][j]\)表示第\(i\)个节点选\(j\)个给\(1\)号头。
但是其他头会对题目有影响啊。
可以说样例给的很套路了。
我给个\(m==2\),说明不给大头就给小头。
没得选择。
但实际上,如果有多个小头。就一定不会吃树枝。
因为当前点吃了是2号头。那么那个点的儿子让3号吃就可以了。
再往下的一层给2号。以此交替。
所以我们就可以用\(f[i][j][0/1]\)表示\(1\)号头取不取了。
因为其他的节点的贡献就在于\(m==2\)?边权:0。
那么转移为

for(int j=0;j<=k;j++)
{ for(int t=0;t<=j;t++){f[x][j][0]=min(f[x][j][0],min(dp[j-t][0]+f[v][t][1],dp[j-t][0]+f[v][t][0]+(m==2)*e[i].v)); f[x][j][1]=min(f[x][j][1],min(dp[j-t][1]+f[v][t][0],dp[j-t][1]+f[v][t][1]+e[i].v)); }
}
//注意这里的f数组不会及时更新。要用dp数组先代替。因为f越来越小对后面的选择会有后效性。

代码

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
const int N=305;
int n,m,k,f[N][N][2],dp[N][2];
struct node{int to,nex,v;
}e[N<<1];
int num,head[N];
int read(){int x=0,w=1;char ch=getchar();while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*w;
}void add(int from,int to,int v){num++;e[num].to=to;e[num].v=v;e[num].nex=head[from];head[from]=num;
}void dfs(int x,int fa){f[x][1][1]=f[x][0][0]=0;for(int i=head[x];i;i=e[i].nex){int v=e[i].to;if(v==fa)continue;dfs(v,x);for(int j=0;j<=k;j++){dp[j][0]=f[x][j][0];dp[j][1]=f[x][j][1];}memset(f[x],63,sizeof(f[x]));for(int j=0;j<=k;j++){for(int t=0;t<=j;t++){f[x][j][0]=min(f[x][j][0],min(dp[j-t][0]+f[v][t][1],dp[j-t][0]+f[v][t][0]+(m==2)*e[i].v));f[x][j][1]=min(f[x][j][1],min(dp[j-t][1]+f[v][t][0],dp[j-t][1]+f[v][t][1]+e[i].v));}}}
}int main(){n=read();m=read();k=read();if(m-1>n-k){printf("-1");return 0;}for(int i=1;i<n;i++){int x=read(),y=read(),z=read();add(x,y,z);add(y,x,z);}memset(f,63,sizeof(f));dfs(1,0);printf("%d\n",f[1][k][1]);return 0;
}

转载于:https://www.cnblogs.com/hhh1109/p/9622874.html

[NOI2002]贪吃的九头龙(树形dp)相关推荐

  1. NOI2002 贪吃的九头龙

    P2940 贪吃的九头龙 时间: 1000ms / 空间: 65536KiB / Java类名: Main 描述 贪吃的九头龙(dragon.pas/c/cpp) [问题描述] 传说中的九头龙是一种特 ...

  2. vijos 1523 贪吃的九头龙

    http://www.elijahqi.win/archives/1191 背景 安徽省芜湖市第二十七中学测试题 NOI 2002 贪吃的九头龙(dragon) Description:Officia ...

  3. BSOJ 1480 贪吃的九头龙

    BSOJ 1480 贪吃的九头龙 NOI原题,下了数据,都过了.但是OJ现在挂了... 首先,脑袋的数量都是唬人的.如果至少3个脑袋的话,完全可以做到不让两个小头在一起(不过当只有2个头的时候得特别考 ...

  4. 【NOI2002】贪吃的九头龙

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

  5. codevs贪吃的九头龙

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

  6. codevs1746 贪吃的九头龙

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

  7. 九大背包问题专题--有依赖的背包问题(树形Dp结合)

    9.有依赖的背包问题 问题: 有N件物品和一个容量是V的背包. 物品之间具有依赖关系,且依赖关系组成一棵树的形状.如果选择一个物品,则必须选择它的父节点. 如图所示 如果选择物品5,则必须选择物品1和 ...

  8. LibreOJ #2478.「九省联考 2018」林克卡特树 树形dp+带权二分

    题意 给出一棵n个节点的树和k,边有边权,要求先从树中选k条边,然后把这k条边删掉,再加入k条边权为0的边,满足操作完后的图仍然是一棵树.问新树的带权直径最大是多少. n,k≤3∗105n,k≤3∗1 ...

  9. 最大搜索二叉子树大小(树形dp)

    给定一颗二叉树的头节点head,返回这棵二叉树中最大的二叉搜索子树 (二叉搜索树:该二叉树中左子树所有节点比它小,右子树所有节点比它大 ): 思路: 这是一道分析可能性求解在二叉树上做类似动态规划的问 ...

  10. 蓝桥杯节点选择(java)第一道树形dp分析

    蓝桥杯 节点选择 问题描述 有一棵 n 个节点的树,树上每个节点都有一个正整数权值.如果一个点被选择了,那么在树上和它相邻的点都不能被选择.求选出的点的权值和最大是多少? 输入格式 第一行包含一个整数 ...

最新文章

  1. linux分区转换gpt命令,Linux中磁盘如何转换GPT格式
  2. python坐标定位_Python_元素定位浏览器坐标定位
  3. 渗透攻击红队百科全书
  4. 10.C++-构造函数初始化列表、类const成员、对象构造顺序、析构函数
  5. 微软Exchange Server 2010 SP1下载
  6. 如何个性化更改Eclipse字体及背景颜色
  7. php think run 后台运行问题
  8. bex5 mysql_bex5 库存系统的增删改查等功能对MYSQL数据库的维护操作 Windows Develop 276万源代码下载- www.pudn.com...
  9. Pdf格式文件怎么修改
  10. 计算机激光鼠标,差评终结者:激光鼠标就是比光电的好?
  11. 关于 gcc/g++编译选项: -fPIC 功能的解释
  12. Chrome浏览器87端口限制问题
  13. X.509证书DN之详解
  14. mysql5.155安装教程_git快速入门
  15. 关于MongoDB报错:connecting to: mongodb://127.0.0.1:27017/?compressors=disabledgssapiServiceName=mongodb
  16. java rtp 分片_RTP 协议解包为 H264 裸流
  17. 兄弟连 职业素质改进计划个人总结
  18. 圣思园java.doc_Java Web学习历程-(基于圣思园视频教程)
  19. 工业计算机检验标准,企业标准规范工业控制计算机检验标准.doc
  20. git访问远程服务器文件,git访问远程服务器文件

热门文章

  1. c语言中断函数作用,进一步理解中断函数
  2. STM32F103时钟系统
  3. Python简单实现人脸识别检测, 对某平台美女主播照片进行评分排名
  4. 开发谷歌浏览器翻译插件
  5. Android intent.Action 参数值及对应功能介绍(转)
  6. 外来工作人员如何提取上海住房公积金
  7. 全网最通俗易懂的「插屏广告」接入方法
  8. 电子计算机是采用什么进制法,计算机内部使用什么进制
  9. Julia两天极速入门学习笔记
  10. python paramiko ssh-解决强制修改密码登录问题