HDU 5293 Tree chain problem 树形dp+dfs序+树状数组+LCA
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5293
题意:
给你一些链,每条链都有自己的价值,求不相交不重合的链能够组成的最大价值。
题解:
树形dp,
对于每条链u,v,w,我们只在lca(u,v)的顶点上处理它
让dp[i]表示以i为根的子树的最大值,sum[i]表示dp[vi]的和(vi为i的儿子们)
则i点有两种决策,一种是不选以i为lca的链,则dp[i]=sum[i]。
另一种是选一条以i为lca的链,那么有转移方程:dp[i]=sigma(dp[vj])+sigma(sum[kj])+w。(sigma表示累加,vj表示那些不在链上的孩子们,kj表示在链上的孩子们)
为了便于计算,我们处理出dp[i]=sum[i]-sigma(dp[k]-sum[k])+w=sum[i]+sigma(sum[k]-dp[k])+w。
利用dfs序和树状数组可以logn算出sigma(sum[k]-dp[k])。
#pragma comment(linker,"/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
using namespace std; const int maxn = ;
const int maxb= ; struct Node {
int u, v, w;
Node(int u, int v, int w) :u(u), v(v), w(w) {}
}; int n, m;
vector<Node> que[maxn];
vector<int> G[maxn];
int lca[maxn][maxb],in[maxn],out[maxn],dep[maxn],dfs_cnt;
int sumv[maxn];
int dp[maxn],sum[maxn]; //计算dfs序,in,out;预处理每个订点的祖先lca[i][j],表示i上面第2^j个祖先,lca[i][0]表示父亲
void dfs(int u, int fa,int d) {
in[u] = ++dfs_cnt;
lca[u][] = fa; dep[u] = d;
for (int j = ; j < maxb; j++) {
int f = lca[u][j - ];
lca[u][j] = lca[f][j - ];
}
for (int i = ; i < G[u].size(); i++) {
int v = G[u][i];
if (v == fa) continue;
dfs(v, u, d + );
}
out[u] = ++dfs_cnt;
}
//在线lca,o(n*logn)预处理+o(logn)询问
int Lca(int u, int v) {
if (dep[u] < dep[v]) swap(u, v);
//二进制倍增法,u,v提到相同高度
for (int i = maxb - ; i >= ; i--) {
if (dep[lca[u][i]] >= dep[v]) u = lca[u][i];
}
//当lca为u或者为v的时候
if (u == v) return u;
//lca不是u也不是v的情况
//一起往上提
for (int i = maxb - ; i >= ; i--) {
if (lca[u][i] != lca[v][i]) {
u = lca[u][i];
v = lca[v][i];
}
}
return lca[u][];
}
//树状数组
int get_sum(int x) {
int ret = ;
while (x > ) {
ret += sumv[x];
x -= x&(-x);
}
return ret;
} void add(int x, int v) {
while (x <maxn) {
sumv[x] += v;
x += x&(-x);
}
}
//树形dp(用到dfs序和树状数组来快速计算链)
//dfs序+树状数组的想法可以自己在纸上画画图,
void solve(int u,int fa) {
for (int i = ; i < G[u].size(); i++) {
int v = G[u][i];
if (v == fa) continue;
solve(v, u);
sum[u] += dp[v];
}
dp[u] = sum[u];
for (int i = ; i < que[u].size(); i++) {
Node& nd = que[u][i];
//get_sum(in[nd.u])处理的是lca(u,v)到u点这条路径的所有顶点
//get_sum(out[nd.v])处理的是lca(u,v)到v点这条路径的所有顶点
dp[u] = max(dp[u], sum[u] + get_sum(in[nd.u]) + get_sum(in[nd.v]) + nd.w);
}
add(in[u], sum[u] - dp[u]);
add(out[u], dp[u] - sum[u]);
} void init() {
dfs_cnt = ;
for (int i = ; i <= n; i++) G[i].clear();
for (int i = ; i <= n; i++) que[i].clear();
memset(lca, , sizeof(lca));
memset(sumv, , sizeof(sumv));
memset(sum, , sizeof(sum));
memset(dp, , sizeof(dp));
} int main() {
int tc;
scanf("%d", &tc);
while (tc--) {
scanf("%d%d", &n, &m);
init();
for (int i = ; i < n; i++) {
int u, v;
scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
dfs(, ,);
while (m--) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
//每条链在Lca的位置上处理,这样符合dp的无后效性
que[Lca(u, v)].push_back(Node(u, v, w));
}
solve(, );
printf("%d\n", dp[]);
}
return ;
}
/*
1
7 111
1 2
1 3
2 4
2 5
3 6
3 7 3 3
1 2
1 3
1 1 1
2 2 2
3 3 3 3 3
1 2
1 3
1 1 1
1 2 3
3 3 1
*/
HDU 5293 Tree chain problem 树形dp+dfs序+树状数组+LCA的更多相关文章
- HDU 5293 Annoying problem 树形dp dfs序 树状数组 lca
Annoying problem 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 Description Coco has a tree, w ...
- [HDU 5293]Tree chain problem(树形dp+树链剖分)
[HDU 5293]Tree chain problem(树形dp+树链剖分) 题面 在一棵树中,给出若干条链和链的权值,求选取不相交的链使得权值和最大. 分析 考虑树形dp,dp[x]表示以x为子树 ...
- 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)
题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...
- 刷题总结——Tree chain problem(HDU 5293 树形dp+dfs序+树状数组)
题目: Problem Description Coco has a tree, whose vertices are conveniently labeled by 1,2,…,n.There ar ...
- HDU 5293 Tree chain problem 树形DP
题意: 给出一棵\(n\)个节点的树和\(m\)条链,每条链有一个权值. 从中选出若干条链,两两不相交,并且使得权值之和最大. 分析: 题解 #include <cstdio> #incl ...
- POJ 2763"Housewife Wind"(DFS序+树状数组+LCA)
传送门 •题意 一对夫妇居住在 xx村庄,给村庄有 $n$ 个小屋: 这 $n$ 个小屋之间有双向可达的道路,不会出现环,即所构成的图是个树: 从 $a_i$ 小屋到 $b_i$ 小屋需要花费 $w_ ...
- BZOJ 2819: Nim( nim + DFS序 + 树状数组 + LCA )
虽然vfleaking好像想卡DFS...但我还是用DFS过了... 路径上的石堆异或和=0就是必败, 否则就是必胜(nim游戏). 这样就变成一个经典问题了, 用DFS序+BIT+LCA就可以在O( ...
- POJ 3321:Apple Tree + HDU 3887:Counting Offspring(DFS序+树状数组)
http://poj.org/problem?id=3321 http://acm.hdu.edu.cn/showproblem.php?pid=3887 POJ 3321: 题意:给出一棵根节点为1 ...
- Codeforces Round #225 (Div. 1) C. Propagating tree dfs序+ 树状数组或线段树
C. Propagating tree Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/383/p ...
随机推荐
- javascript 数组对象与嵌套循环写法
'use strict' var info=[{"name":"最近想跳河","interst":["历史"," ...
- C#中sizeof的用法实例分析
这篇文章主要介绍了C#中sizeof的用法,包括了常见的用法及注释事项,需要的朋友可以参考下. sizeof是C#中非常重要的方法,本文就以实例形式分析C#中sizeof的用法.分享给大家供大家参 ...
- luigi学习2-在hadoop上运行Top Artists
一.AggregateArtistsHadoop class AggregateArtistsHadoop(luigi.contrib.hadoop.JobTask): date_interval = ...
- php安装redis扩展连接redis服务器
扩展包的下载地址:https://github.com/nicolasff/phpredis/archive/2.2.4.tar.gz tar xf phpredis-2.2.4.tar.gz cd ...
- GoLang安装
GoLang的官网被墙,镜像下载地址:http://tip.golang.so/dl/ 或者 http://golang.so/dl/ 安装说明:http://tip.golang.so/doc/i ...
- Php output buffering缓存及程序缓存
在php中有时为了控制程序的输出显示顺序,提供了output buffering缓存(php自身缓存机制). 若Ob缓存开启,需要输出的就先存在ob缓存里,再到程序缓存里.若没有开启,则直接进入 ...
- PHP文件上传错误类型及说明
从 PHP 4.2.0 开始,PHP 将随文件信息数组一起返回一个对应的错误代码.该代码可以在文件上传时生成的文件数组中的 error 字段中被找到,也就是 $_FILES['userfile'][' ...
- 容易被忽略的事----sql语句中select语句的执行顺序
关于Sql中Select语句的执行顺序,一直很少注意这个问题,对于关键字的使用也很随意,至于效率问题,因为表中的数据量都不是很大,所以也不是很在意. 今天在一次面试的时候自己见到了,感觉没一点的印象, ...
- R语言的字符串处理
R语言字符串的拼接 content<-paste("124235","789","124",sep="@") 运行 ...
- this的使用方法
当一个对象创建后,Java虚拟机(JVM)就会给这个对象分配一个引用自身的指针,这个指针的名字就是this.this是指向对象本身的一个指针.this只和特定的对象关联,而不和类关联,同一个类的不同对 ...