题目链接:

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的更多相关文章

  1. HDU 5293 Annoying problem 树形dp dfs序 树状数组 lca

    Annoying problem 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 Description Coco has a tree, w ...

  2. [HDU 5293]Tree chain problem(树形dp+树链剖分)

    [HDU 5293]Tree chain problem(树形dp+树链剖分) 题面 在一棵树中,给出若干条链和链的权值,求选取不相交的链使得权值和最大. 分析 考虑树形dp,dp[x]表示以x为子树 ...

  3. 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)

    题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...

  4. 刷题总结——Tree chain problem(HDU 5293 树形dp+dfs序+树状数组)

    题目: Problem Description Coco has a tree, whose vertices are conveniently labeled by 1,2,…,n.There ar ...

  5. HDU 5293 Tree chain problem 树形DP

    题意: 给出一棵\(n\)个节点的树和\(m\)条链,每条链有一个权值. 从中选出若干条链,两两不相交,并且使得权值之和最大. 分析: 题解 #include <cstdio> #incl ...

  6. POJ 2763"Housewife Wind"(DFS序+树状数组+LCA)

    传送门 •题意 一对夫妇居住在 xx村庄,给村庄有 $n$ 个小屋: 这 $n$ 个小屋之间有双向可达的道路,不会出现环,即所构成的图是个树: 从 $a_i$ 小屋到 $b_i$ 小屋需要花费 $w_ ...

  7. BZOJ 2819: Nim( nim + DFS序 + 树状数组 + LCA )

    虽然vfleaking好像想卡DFS...但我还是用DFS过了... 路径上的石堆异或和=0就是必败, 否则就是必胜(nim游戏). 这样就变成一个经典问题了, 用DFS序+BIT+LCA就可以在O( ...

  8. 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 ...

  9. 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 ...

随机推荐

  1. (二)、NodeJS 、Express4安装使用方法

    第一步:安装Nodejs 第二步:安装express等部件 1.打开命令窗口,安装express.jade npm install -g express npm install -g express- ...

  2. ios网络:应用一个请求的7个步骤

    Splitting big tasks into small tasks is often one of the best ways to solve a problem. Thus, in the ...

  3. canvas 绘制矩形和圆形

    canvas绘制有两神方法:1).填充(fill)填充是将图形内部填满. 2).绘制边框 (stroke)绘制边框是不把图形内部填满,只是绘制图形的外框. 当我们在绘制图形的时候,首先要设定好绘制的样 ...

  4. varnish状态引擎2

    如何让varnish支持虚拟主机: if (req.http.host = "www.nihao.com") { } 强制对某资源的请求,不检查缓存: 上图表示以/test1.ht ...

  5. recurse_array_change_key_case()递规返回字符串键名全为小写或大写的数组

    //递归返回字符串键名全为小写或大写的数组function recurse_array_change_key_case(&$input, $case = CASE_LOWER){    if( ...

  6. 7-ZIP实现数据高度压缩

    From:http://www.cnblogs.com/killerlegend/p/3746395.html Author:KillerLegend Date:2013.5.22 选中文件,鼠标右键 ...

  7. 【转】操作ini文件

    一.INI文件的结构: ; 注释 [小节名] 关键字=值 INI文件有多个小节,每个小节又有多个关键字, “=”后面是该关键字的值.  值的类型有三种:字符串.整型数值和布尔值. 其中字符串存贮在IN ...

  8. DevExpress 关于 GridView 表格编辑中 点击其他按钮里导致 值未取到处理

    只需要给添加以下代码 在执行其他按钮前调 用一下 就可以了:主要是用来关闭编辑以及更新当前行编辑内容 this.gridControl1.FocusedView.CloseEditor(); this ...

  9. C# 程序开始主要是写类和方法 的基本步骤和调用方法

    主程序的使用方式以及调用方法字段.属性.方法 using System; using System.Collections.Generic; using System.Linq; using Syst ...

  10. 给Activity设置背景颜色

    为了使得错误提示更加显眼,再用Toast+振动效果之外考虑变换整个activity的背景颜色. 尝试一: activity并没像winform一样直接给个属性来设置,就想获取整个activity的la ...