Codeforces1223E. Paint the Tree(树形dp)
题目链接:传送门
题目大意:
给出节点数为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)的更多相关文章
- E. Paint the Tree 树形dp
E. Paint the Tree 题目大意:给你一棵树,每一个点都可以染k种颜色,你拥有无数种颜色,每一种颜色最多使用2次,如果一条边的两个节点拥有同一种颜色,那么就说 这条边是饱和的,一个树的价值 ...
- 熟练剖分(tree) 树形DP
熟练剖分(tree) 树形DP 题目描述 题目传送门 分析 我们设\(f[i][j]\)为以\(i\)为根节点的子树中最坏时间复杂度小于等于\(j\)的概率 设\(g[i][j]\)为当前扫到的以\( ...
- 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: ...
- 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 ...
- codeforces 161D Distance in Tree 树形dp
题目链接: http://codeforces.com/contest/161/problem/D D. Distance in Tree time limit per test 3 secondsm ...
- hdu6035 Colorful Tree 树形dp 给定一棵树,每个节点有一个颜色值。定义每条路径的值为经过的节点的不同颜色数。求所有路径的值和。
/** 题目:hdu6035 Colorful Tree 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6035 题意:给定一棵树,每个节点有一个颜色值.定 ...
- 5.10 省选模拟赛 tree 树形dp 逆元
LINK:tree 整场比赛看起来最不可做 确是最简单的题目. 感觉很难写 不过单独考虑某个点 容易想到树形dp的状态. 设f[x]表示以x为根的子树内有黑边的方案数. 白边方案只有一种所以不用记录. ...
- Codeforces Round #263 Div.1 B Appleman and Tree --树形DP【转】
题意:给了一棵树以及每个节点的颜色,1代表黑,0代表白,求将这棵树拆成k棵树,使得每棵树恰好有一个黑色节点的方法数 解法:树形DP问题.定义: dp[u][0]表示以u为根的子树对父亲的贡献为0 dp ...
- codeforces Round #263(div2) D. Appleman and Tree 树形dp
题意: 给出一棵树,每个节点都被标记了黑或白色,要求把这棵树的其中k条变切换,划分成k+1棵子树,每颗子树必须有1个黑色节点,求有多少种划分方法. 题解: 树形dp dp[x][0]表示是以x为根的树 ...
随机推荐
- docker-compose部署zk和kafka
version: '3.4' services: zk1: image: zookeeper restart: always hostname: zk1 container_name: zk1 por ...
- Centos 7 安装tomcat并部署jar实录
本文目的 纯属记录,以备后查. 1.安装JAVA JDK 安装jdk略. 配置JDK,打开/etc/profile文件,在最后添加如下代码: JAVA_HOME=/usr/java/jdk1..0_2 ...
- Linux监控命令之==>netstat
一.命令说明 netstat 命令用于显示本机网络连接.运行端口.路由表等信息 二.参数说明 -a (all):显示一个所有的有效连接信息列表,包括已建立的连接(ESTABLISHED),也包括监听连 ...
- Oracle 数据字典视图(V$,GV$,X$)
常用的几个数据字典: user_objects : 记录了用户的所有对象,包含表.索引.过程.视图等信息,以及创建时间,状态是否有效等信息,是非DBA用户的大本营.想知道自己有哪些对象,往这里查. u ...
- 在Linux命令行模式安装VMware Tools
在Linux命令行模式安装VMware Tools 方法/步骤1: 首先启动CentOS 7,在VMware中点击上方“VM”,点击“Install VMware Tools...”(如已安装则显示“ ...
- 【VS开发】ActiveX控件如何定制属性?
在很多场合下会存在这样的需求,那就是使用方在实际使用控件之前就想控件已经做了相应的处理比如加载的控件版本不正确等,或者需要在加载时才确定能够使用的功能集:这个时候传统的配置文件已经无法满足这种类型的需 ...
- HTML标签-->列表,表格
只有努力奔跑,才能一直停留在原地. 无序列表 <ul><!--默认列表编号为(实心圆)--> <li>第一项</li> <li>第二项< ...
- 小记---------手动执行脚本正常执行,使用crontab定时执行时 不执行
可能出现的原因就是因为crontab不会从用户的/etc/profile文件中读取环境变量,所以就出现 使用定时crontab执行时 无法执行 抛错 所以在使用crontab 定时执行脚本时 在脚本 ...
- 2014年北京 happy matt friends(dp + 滚动数组优化)
Happy Matt Friends Time Limit: 6000/6000 MS (Java/Others) Memory Limit: 510000/510000 K (Java/Oth ...
- shiro三连斩之概念
1, 什么是Shiro? Shiro是一个安全框架,用于解决系统的认证和授权问题,同时提供了会话管理,数据加密,与WEB集成,缓存等机制. Authentication:身份认证/登录,验证用户是不是 ...