题目链接:传送门

题目大意:

给出节点数为n的一棵带权树,和每个点的最大染色数k。一条边的权重w能产生价值w的条件是,这条边的两端的点至少有一个颜色相同。颜色种类数无限,但每种只能使用两次,问能产生的最大总价值。

思路:

(这两天刷dp专题ing,一上来就会朝dp方面想。看到题目中给出的还是个树,直接盲猜树形dp开始搓状态。结果还tm都搓出来了,以后再看到树会不会巴甫洛夫效应了呀!)

这题考虑树形dp。树形dp的话一般都是考虑一棵以u为根的树的状态,能不能很好地从以u的儿子v为根的子树的状态转移过来。

这题中想从v转移到u,只用考虑u和v有没有染相同颜色即可。

所以用f[u][0/1]表示以u为根的子树,u和u的父亲染不染相同颜色的条件下(0表示不染同色,1反之),产生的最大价值。

在f[u][0]中u最多能和k个儿子染相同的颜色,这些点产生的贡献是$\sum_{u是v的父亲} f[v][1] + edge_{u, v}$,此外还要加上剩余的所有没考虑过的v的f[v][0]。

同理在f[u][1]中u最多能和k-1个儿子染相同的颜色。

考虑如何选择这k/k-1个儿子v:

他们如果连父亲,产生的贡献为f[v][1] + $edge_{u, v}$,如果不连父亲,产生的贡献是f[v][0]。连上父亲对总答案的贡献的增量为f[v][1] + $edge_{u,v}$ - f[v][0],根据这个增量排序从大到小取k/k-1个就可以了(注意一下可能有增量小于0的情况)

代码:O(nlogn)

#include <bits/stdc++.h>
#define fast ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define N 500005
#define M 500005
#define INF 0x3f3f3f3f
#define mk(x) (1<<x) // be conscious if mask x exceeds int
#define sz(x) ((int)x.size())
#define upperdiv(a,b) (a/b + (a%b>0))
#define mp(a,b) make_pair(a, b)
#define endl '\n'
#define lowbit(x) (x&-x) using namespace std;
typedef long long ll;
typedef double db; /** fast read **/
template <typename T>
inline void read(T &x) {
x = ; T fg = ; char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-') fg = -;
ch = getchar();
}
while (isdigit(ch)) x = x*+ch-'', ch = getchar();
x = fg * x;
}
template <typename T, typename... Args>
inline void read(T &x, Args &... args) { read(x), read(args...); }
template <typename T>
inline void write(T x) {
int len = ; char c[]; if (x < ) putchar('-'), x = -x;
do{++len; c[len] = x% + '';} while (x /= );
for (int i = len; i >= ; i--) putchar(c[i]);
}
template <typename T, typename... Args>
inline void write(T x, Args ... args) { write(x), write(args...); } int n, k;
struct Node{
int u;
ll val;
bool operator < (const Node& x) const {
return val > x.val;
}
}; int tot = ;
int head[N], nxt[M<<], ver[M<<];
ll wei[M<<];
void addEdge(int u, int v, ll w) { nxt[++tot] = head[u], ver[tot] = v, wei[tot] = w, head[u] = tot; } bool added[N][];
ll f[N][];
void dfs(int u, int p) {
vector <Node> nodes;
for (int i = head[u]; i != -; i = nxt[i]) {
int v = ver[i]; ll w = wei[i];
if (v == p) continue;
dfs(v, u);
nodes.push_back(Node{v, f[v][]+w - f[v][]});
}
sort(nodes.begin(), nodes.end());
for (int i = ; i < sz(nodes) && i < k; i++) {
Node tmp = nodes[i];
if (tmp.val <= )
break;
if (i < k-) {
f[u][] += tmp.val + f[tmp.u][];
added[tmp.u][] = true;
}
f[u][] += tmp.val + f[tmp.u][];
added[tmp.u][] = true;
}
for (int i = head[u]; i != -; i = nxt[i]) {
int v = ver[i];
if (v == p) continue;
if (!added[v][])
f[u][] += f[v][];
if (!added[v][])
f[u][] += f[v][];
}
}
int main()
{
int q; read(q);
while (q--) {
read(n, k);
tot = ;
for (int i = ; i <= n; i++) {
head[i] = -;
added[i][] = added[i][] = false;
f[i][] = f[i][] = ;
}
for (int i = ; i <= n-; i++) {
int u, v; ll w; read(u, v, w);
addEdge(u, v, w);
addEdge(v, u, w);
}
dfs(, -);
ll ans = f[][];
cout << ans << endl;
}
return ;
}

Codeforces1223E. Paint the Tree(树形dp)的更多相关文章

  1. E. Paint the Tree 树形dp

    E. Paint the Tree 题目大意:给你一棵树,每一个点都可以染k种颜色,你拥有无数种颜色,每一种颜色最多使用2次,如果一条边的两个节点拥有同一种颜色,那么就说 这条边是饱和的,一个树的价值 ...

  2. 熟练剖分(tree) 树形DP

    熟练剖分(tree) 树形DP 题目描述 题目传送门 分析 我们设\(f[i][j]\)为以\(i\)为根节点的子树中最坏时间复杂度小于等于\(j\)的概率 设\(g[i][j]\)为当前扫到的以\( ...

  3. hdu-5834 Magic boy Bi Luo with his excited tree(树形dp)

    题目链接: Magic boy Bi Luo with his excited tree Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: ...

  4. CF 461B Appleman and Tree 树形DP

    Appleman has a tree with n vertices. Some of the vertices (at least one) are colored black and other ...

  5. codeforces 161D Distance in Tree 树形dp

    题目链接: http://codeforces.com/contest/161/problem/D D. Distance in Tree time limit per test 3 secondsm ...

  6. hdu6035 Colorful Tree 树形dp 给定一棵树,每个节点有一个颜色值。定义每条路径的值为经过的节点的不同颜色数。求所有路径的值和。

    /** 题目:hdu6035 Colorful Tree 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6035 题意:给定一棵树,每个节点有一个颜色值.定 ...

  7. 5.10 省选模拟赛 tree 树形dp 逆元

    LINK:tree 整场比赛看起来最不可做 确是最简单的题目. 感觉很难写 不过单独考虑某个点 容易想到树形dp的状态. 设f[x]表示以x为根的子树内有黑边的方案数. 白边方案只有一种所以不用记录. ...

  8. Codeforces Round #263 Div.1 B Appleman and Tree --树形DP【转】

    题意:给了一棵树以及每个节点的颜色,1代表黑,0代表白,求将这棵树拆成k棵树,使得每棵树恰好有一个黑色节点的方法数 解法:树形DP问题.定义: dp[u][0]表示以u为根的子树对父亲的贡献为0 dp ...

  9. codeforces Round #263(div2) D. Appleman and Tree 树形dp

    题意: 给出一棵树,每个节点都被标记了黑或白色,要求把这棵树的其中k条变切换,划分成k+1棵子树,每颗子树必须有1个黑色节点,求有多少种划分方法. 题解: 树形dp dp[x][0]表示是以x为根的树 ...

随机推荐

  1. 如何用ORM自定义排序

    ORM连接的数据库不同,方法也不同 postgresql: a.extra(select={"new_order":"position(status in '2,3,4, ...

  2. linux (一)

    一.文件目录 cd 目录进出 pwd 查看路径 ls:ll 查看目录 mkdir : mkdir -p  app/test 创建目录 touch 创建文件 rm :rm -r 递归 -f 强制 mv ...

  3. EMQ插件组合实现物联网边缘平台的设备通信管理

    上一篇随笔我简单的记录了我对EMQ插件开发的了解过程,最后发现还是可以组合复用已有插件,因此这篇随笔用于记录使用的情况以及是否达到预期. 首先测试mysql认证插件的使用方式: emqx_auth_m ...

  4. Tomcat指定JDK

    那么当有多个JDK时,是否可以为Tomcat这类应用程序指定对应的JDK版本 如下图,只需修改catalina.sh 即可,不需要修改“tomcat/bin/setclasspath.sh” . “t ...

  5. java之消息队列ActiveMQ实践

    原创论文:https://www.cnblogs.com/goujh/p/8510239.html 消息队列的应用场景: 消息队列应用场景 异步处理,应用解耦,流量削锋和消息通讯四个场景 异步处理: ...

  6. flutter dialog

    flutter Dialog import 'dart:math'; import 'package:flutter/material.dart'; import 'test.dart'; impor ...

  7. flutter Waiting for another flutter command to release the startup lock…

    flutter安装完成后执行flutter doctor ,一直提示如下: Waiting for another flutter command to release the startup loc ...

  8. jquery.validate.js使用之自定义表单验证规则

    jquery.validate.js使用之自定义表单验证规则,下面列出了一些常用的验证法规则 jquery.validate.js演示查看 jquery validate强大的jquery表单验证插件 ...

  9. 再谈 Devstack(Rocky)

    目录 文章目录 目录 前言 网络拓扑 运行环境 要点 步骤 前言 之前写过一篇<Openstack 实现技术分解 (1) 开发环境 - Devstack 部署案例详解>,随着 Devsta ...

  10. Java学习之==>数组【array】

    一.定义数组 /** * 一维数组定义 * * 为数组插入元素 */ public void case1() { // 声明 int[] arr1; // 声明+初始化 int[] arr2 = ne ...