大意就是把一棵树的点染成m种颜色,其中1号点的颜色必须染恰好k个节点。

总代价是所有两端点颜色相同的边的边权。

求最小代价。

解:可以分为m == 2和m > 2两个题。

m > 2时有代价的边的两端点显然是一号点色的(设为白色)。

m == 2的时候还要计算两端点是另外一种颜色的边的贡献(黑色)。

状态设计就是f[x][j][0/1]表示x为根的子树中染了j个白色点,x号点染/不染的最小代价。

转移的时候做一个类似树上背包的转移即可。

注意m == 2的时候,更新f[i][j][0]合并子树的时候要把原来的那个值覆盖掉,因为子节点也是0的时候会有代价,所以不能保留原来的没有计算这个代价的值。

我比较菜,一开始没发现要分成两个题,就写了两个DFS函数...

 #include <cstdio>
#include <algorithm>
#include <cstring> const int N = ; struct Edge {
int nex, v, len;
}edge[N << ]; int top; int f[N][N][], e[N], n, k; inline void add(int x, int y, int z) {
top++;
edge[top].v = y;
edge[top].len = z;
edge[top].nex = e[x];
e[x] = top;
return;
} void DFS_2(int x, int fa) {
f[x][][] = ;
f[x][][] = ;
for(int i = e[x]; i; i = edge[i].nex) {
int y = edge[i].v;
if(y == fa) {
continue;
}
DFS_2(y, x);
for(int j = k; j >= ; j--) {
/// f[x][j] [0/1]
int t = 0x3f3f3f3f;
for(int p = j; p >= ; p--) {
t = std::min(t, std::min(f[y][p][] + f[x][j - p][], f[y][p][] + f[x][j - p][] + edge[i].len));
}
f[x][j][] = t;
t = 0x3f3f3f3f;
for(int p = j; p >= ; p--) {
t = std::min(t, std::min(f[y][p][] + f[x][j - p][] + edge[i].len, f[y][p][] + f[x][j - p][]));
}
f[x][j][] = t;
/*for(int p = j; p >= 0; p--) {
f[x][j][0] = std::min(f[x][j][0], f[y][p][0] + f[x][j - p][0] + edge[i].len);
f[x][j][0] = std::min(f[x][j][0], f[y][p][1] + f[x][j - p][0]);
if(j != p) {
if(x == 1 && j == 2)printf("step 0 f[1][2][1] = %d \n", f[1][2][1]);
f[x][j][1] = std::min(f[x][j][1], f[y][p][0] + f[x][j - p][1]);
if(x == 1 && j == 2)printf("step 1 f[1][2][1] = %d \n", f[1][2][1]);
f[x][j][1] = std::min(f[x][j][1], f[y][p][1] + f[x][j - p][1] + edge[i].len);
if(x == 1 && j == 2)printf("step 2 f[1][2][1] = %d \n", f[1][2][1]);
if(x == 1 && j == 4 && y == 2 && p == 2) {
printf("%d + %d \n", f[y][p][0] + f[x][j - p][1]);
}
if(x == 1 && j == 2) {
printf("> f 1 2 1 = %d p = %d \n", f[1][2][1], p);
printf("> %d + %d \n", f[y][p][0], f[x][j - p][1]);
printf("> %d + %d \n", f[y][p][1], f[x][j - p][1] + edge[i].len);
}
}
}*/
}
}
/*for(int j = 0; j <= k; j++) {
printf("f %d %d %d = %d \n", x, j, 0, f[x][j][0]);
*/
return;
} void DFS_1(int x, int fa) {
f[x][][] = ;
f[x][][] = ;
for(int i = e[x]; i; i = edge[i].nex) {
int y = edge[i].v;
if(y == fa) {
continue;
}
DFS_1(y, x);
//
for(int j = k; j >= ; j--) {
/// f[x][j] [0/1]
for(int p = j; p >= ; p--) {
f[x][j][] = std::min(f[x][j][], f[y][p][] + f[x][j - p][]);
f[x][j][] = std::min(f[x][j][], f[y][p][] + f[x][j - p][]);
if(p != j) {
f[x][j][] = std::min(f[x][j][], f[y][p][] + f[x][j - p][]);
f[x][j][] = std::min(f[x][j][], f[y][p][] + f[x][j - p][] + edge[i].len);
}
}
}
}
return;
} int main() {
int m;
memset(f, 0x3f, sizeof(f));
scanf("%d%d%d", &n, &m, &k);
for(int i = , x, y, z; i < n; i++) {
scanf("%d%d%d", &x, &y, &z);
add(x, y, z);
add(y, x, z);
}
if(n - k < m - ) {
puts("-1");
return ;
}
if(m > ) {
DFS_1(, );
printf("%d\n", f[][k][]);
}
else {
DFS_2(, );
printf("%d\n", f[][k][]);
}
return ;
}

AC代码

洛谷P4362 贪吃的九头龙的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. codevs1746 贪吃的九头龙

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

  7. vojis1523 NOI2002 贪吃的九头龙

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

  8. codevs贪吃的九头龙

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

  9. [NOI2002] 贪吃的九头龙

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

随机推荐

  1. 优化CSS重排重绘与浏览器性能

    关于CSS重排和重绘的概念,最近看到不少这方面的文章,觉得挺有用,在制作中考虑浏览器的性能,减少重排能够节省浏览器对其子元素及父类元素的重新渲染:避免过分的重绘也能节省浏览器性能:优化动画,使用3D启 ...

  2. Spark开发第一个程序

    simon@simon-Lenovo-G400:~/.ssh$ touch authorized_keyssimon@simon-Lenovo-G400:~/.ssh$ cat id_rsa.pub ...

  3. 从git中删除 .idea 目录

    将.idea目录加入ignore清单: $ echo '.idea' >> .gitignore   从git中删除idea: $ git rm —cached -r .idea 3 将. ...

  4. linux mysql -- ERROR! The server quit without updating PID file (/usr/local/mysql/data/localhost.localdomain.pid)

    转载 http://blog.csdn.net/caiyaodeng/article/details/45937183 linux 链接mysql 报错 ERROR! The server quit ...

  5. codeforces749B

    Parallelogram is Back CodeForces - 749B 已知平行四边形的三个顶点,求第四个顶点可能的位置.Input输入有三行,每行包括两个整数x和y ( - 1000 ≤ x ...

  6. Mysql(Mariadb)数据库主从复制

    Mysql主从复制的实现原理图大致如下: MySQL之间数据复制的基础是以二进制日志文件(binary log file)来实现的,一台MySQL数据库一旦启用二进制日志后,其作为master,它数据 ...

  7. 如何下载旧版本的MySQL

    可能存在这样的场景,比如一些老系统需要使用MySQL 5.5版本才能运行,其余的不行. 1.登录下载站点 https://dev.mysql.com/downloads/mysql/ 此时的最新版本为 ...

  8. 水课 or not

    很不幸,这学期的毛概老师是个老古董,讲的内容也甚是枯燥和迂腐,个人角度是不太喜欢.然而这也仅仅是站在个人感性的角度,唏嘘一下也就够了.听不下去了,写点东西. 有时候会想,是不是随着自己长大,渐渐地对专 ...

  9. 基准对象object中的基础类型----列表 (四)

    object有如下子类: CLASSES object basestring str unicode buffer bytearray classmethod complex dict enumera ...

  10. HDU2204 Eddy's爱好

    题意:给你一个正整数N,确定在1到N之间有多少个可以表示成M^K(K>1)的数. 解析:一个数N 开K次根后得到M  则小于M的所有数的K次方一定小于N 因为任何一个合数都能分解为素数的乘积 所 ...