题目链接

题意:

  有n个点的一棵树。其中树上有m条已知的链,每条链有一个权值。从中选出任意个不相交的链使得链的权值和最大。

思路:

  树形DP。设dp[i]表示i的子树下的最优权值和,sum[i]表示不考虑i点时子树的最优权值和,即(j是i的儿子),显然dp[i]>=sum[i]。那么问题是考虑i点时dp[i]的值是多少,假设有一条链通过i,且端点a和b都在i的子树里,即LCA(a,b)=i,如果考虑加上这条链的权值,那么a->i, b->i的路上的点v都不能有链经过它们(题目要求链不相交),那么-dp[v],但至少有sum[v],即,其中v是某条链上的点。那么怎么快速求出sigma的值呢,想到树状数组维护前缀和。那么怎么遍历呢,用DFS序遍历,思想和“粮食分配”一样,在L[v]上修改,在R[v]上恢复。

#include <bits/stdc++.h>
using namespace std; const int N = 1e5 + 5;
const int D = 20; struct Chain {
int u, v, w;
};
vector<Chain> chains[N];
vector<int> edges[N];
int dp[N], sum[N];
int n, m;
int tim; void init() {
for (int i=1; i<=n; ++i) {
edges[i].clear ();
chains[i].clear ();
}
} int rt[N][D], dep[N]; void init_LCA() {
for (int j=1; j<D; ++j) {
for (int i=1; i<=n; ++i) {
rt[i][j] = rt[i][j-1] ? rt[rt[i][j-1]][j-1] : 0;
}
}
} int LCA(int u, int v) {
if (dep[u] < dep[v]) swap (u, v);
for (int i=0; i<D; ++i) {
if ((dep[u] - dep[v]) >> i & 1) {
u = rt[u][i];
}
}
if (u == v) return u;
for (int i=D-1; i>=0; --i) {
if (rt[u][i] != rt[v][i]) {
u = rt[u][i];
v = rt[v][i];
}
}
return rt[u][0];
} struct BIT {
int C[N];
int n;
void init(int n) {
this->n = n;
memset (C, 0, sizeof (C));
}
void updata(int i, int x) {
for (; i<=n; i+=i&-i) C[i] += x;
}
int query(int i) {
int ret = 0;
for (; i>0; i-=i&-i) ret += C[i];
return ret;
}
}bsum, bdp; int L[N], R[N]; void DFS(int u, int pa) {
L[u] = tim++;
dep[u] = dep[pa] + 1;
rt[u][0] = pa;
for (auto v: edges[u]) {
if (v == pa) continue;
DFS (v, u);
}
R[u] = tim;
} void DFS(int u) {
sum[u] = 0;
for (auto v: edges[u]) {
if (v == rt[u][0]) continue;
DFS (v);
sum[u] += dp[v];
}
dp[u] = sum[u];
for (auto chain: chains[u]) {
int a = chain.u, b = chain.v, c = chain.w;
int tmp = bsum.query (L[a]) - bdp.query (L[a]) + bsum.query (L[b]) - bdp.query (L[b]);
dp[u] = max (dp[u], sum[u] + tmp + c);
}
bsum.updata (L[u], sum[u]);
bsum.updata (R[u], -sum[u]);
bdp.updata (L[u], dp[u]);
bdp.updata (R[u], -dp[u]);
} void prepare() {
dep[0] = 0;
tim = 1;
DFS (1, 0);
init_LCA ();
bsum.init (n);
bdp.init (n);
} int main() {
int T;
scanf ("%d", &T);
while (T--) {
init ();
scanf ("%d%d", &n, &m);
for (int i=1; i<n; ++i) {
int u, v;
scanf ("%d%d", &u, &v);
edges[u].push_back (v);
edges[v].push_back (u);
} prepare (); for (int i=1; i<=m; ++i) {
int u, v, w;
scanf ("%d%d%d", &u, &v, &w);
int lca = LCA (u, v);
chains[lca].push_back ((Chain) {u, v, w});
} DFS (1);
printf ("%d\n", dp[1]);
}
return 0;
}

  

树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)的更多相关文章

  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. 洛谷P3374 【模板】树状数组 1&&P3368 【模板】树状数组 2题解

    图片来自度娘~~ 树状数组形如上图,是一种快速查找区间和,快速修改的一种数据结构,一个查询和修改复杂度都为log(n),树状数组1和树状数组2都是板子题,在这里进行详解: 求和: 首先我们看一看这个图 ...

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

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

  4. HDU 5293 Tree chain problem 树形dp+dfs序+树状数组+LCA

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 题意: 给你一些链,每条链都有自己的价值,求不相交不重合的链能够组成的最大价值. 题解: 树形 ...

  5. HDU 5293 Train chain Problem - 树链剖分(树状数组) + 线段树+ 树型dp

    传送门 题目大意: 一颗n个点的树,给出m条链,第i条链的权值是\(w_i\),可以选择若干条不相交的链,求最大权值和. 题目分析: 树型dp: dp[u][0]表示不经过u节点,其子树的最优值,dp ...

  6. 线段树(单点更新)/树状数组 HDOJ 1166 敌兵布阵

    题目传送门 /* 线段树基本功能:区间值的和,修改某个值 */ #include <cstdio> #include <cstring> #define lson l, m, ...

  7. 树状数组 Binary Indexed Tree/Fenwick Tree

    2018-03-25 17:29:29 树状数组是一个比较小众的数据结构,主要应用领域是快速的对mutable array进行区间求和. 对于一般的一维情况下的区间和问题,一般有以下两种解法: 1)D ...

  8. [bzoj1901][zoj2112][Dynamic Rankings] (整体二分+树状数组 or 动态开点线段树 or 主席树)

    Dynamic Rankings Time Limit: 10 Seconds      Memory Limit: 32768 KB The Company Dynamic Rankings has ...

  9. HDU 3436--Queue-jumpers (树状数组 or Splay Tree)

    树状数组这个真心想了好久,还是没想出来 %%% www.cppblog.com/Yuan/archive/2010/08/18/123871.html 树状数组求前缀和大于等于k的最大值,第一次看到这 ...

随机推荐

  1. MyBatis中关于别名typeAliases的设置

    第一种:通过在配置文件中typeAlias节点设置type的方式 <?xml version="1.0" encoding="UTF-8" ?> & ...

  2. MyBatis框架在控制台打印Sql语句-遁地龙卷风

    第二版 (-1)写在前面 我用的是MyBatis 3.2.4,Maven Project (0)mybatis-config.xml <settings> <setting name ...

  3. PHP语言中使用JSON和将json还原成数组

    从5.2版本开始,PHP原生提供json_encode()和json_decode()函数,前者用于编码,后者用于解码. 一.json_encode() 1 2 3 4 <?php $arr = ...

  4. JSON中eval与parse的区别

    json的的解析方法 (非原创) json的解析方法共有两种:eval_r() 和 JSON.parse(),使用方法如下: var jsonData = '{"data1":&q ...

  5. asp:Repeater实例备忘

    1.前置部分 <asp:Repeater ID="rptPlanNo" runat="server" OnItemDataBound="rptP ...

  6. How do I get the path of the current executed file in Python?

    First, you need to import from inspect and os from inspect import getsourcefile from os.path import ...

  7. Django (2)

    一.Django基本   程序编写 a. url.py        /index/    ->   func b. views.py def func(request):     # 包含所有 ...

  8. testng 失败自动截图

    testng执行case failed ,testng Listener会捕获执行失败,如果要实现失败自动截图,需要重写Listener的onTestFailure方法 那么首先新建一个Listene ...

  9. sublime一些快捷键

    语法: 后代:> 缩写:nav>ul>li <nav> <ul> <li></li> </ul> </nav> ...

  10. .net项目中上传的图片或者文件太大 无法上传

    最近做项目的时候  用户提出要上传大图片  一张图片有可能十几兆  本来用的第三方的上传控件  有限制图片上传大小的设置 以前设置的是2M  按照用户的要求  以为直接将限制图片上传大小的设置改下就可 ...