题目链接

题意:

  有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. Matlab与Windows桌面提醒

    最近在实验室用Matlab做实验,一次训练下来最少得也得5到10分钟吧.在Matlab运行的过程中,又不太好去做别的事情,因为5到10分钟的时间实在有点短.但是,眼睁睁看着代码的运行的话,5分钟又实在 ...

  2. EBS提交请求出现REP-3000错误

    在AIX上利用并发请求提交报表的時候,出现如下错误:REP-3000: Internal error starting Oracle Toolkit.这是因为Report Server需要X-Wind ...

  3. 使用ICSharpCode.SharpZipLib.Zip类库解压zip文件的方法

    public static bool ZipExtractFile(string zipFilePath,string targetPath) { FastZip fastZip = new Fast ...

  4. OC与c混编实现Java的String的hashcode()函数

    首先,我不愿意大家需要用到这篇文章里的代码,因为基本上你就是被坑了. 起因:我被Java后台人员坑了一把,他们要对请求的参数增加一个额外的字段,字段的用途是来校验其余的参数是否再传递过程中被篡改或因为 ...

  5. jvm--2.类加载机制

    3.JVM类加载机制 (1)类加载机制 虚拟机把描述类的数据从Class文件,用ClassLoader ,加载到内存,并对数据进行校验.转换解析和初始化,最终形成虚拟机直接使用的java类型, 这就是 ...

  6. 第四篇 基于.net搭建热插拔式web框架(RazorEngine实现)

    在开头也是先给大家道个歉,由于最近准备婚事导致这篇文章耽误了许久,同时也谢谢老婆大人对我的支持. 回顾上篇文章,我们重造了一个controller,这个controller中用到了视图引擎,我们的视图 ...

  7. bash学习

    if 的使用 declare -i x=10 if [ $x -lt 14 ];then echo $x'小于14'; elif [ $x -gt 9 ];then echo $x'大于9'; els ...

  8. 关于python的10个建议,比较适合新手吧.

    关于python的十个建议 http://safehammad.com/downloads/python-idioms-2014-01-16.pdf

  9. c++单链表基本功能

    head_LinkNode.h /*单链表类的头文件*/#include<assert.h>#include"compare.h"typedef int status; ...

  10. vs2012 安装entity framework

    1.安装vs2012 2.打开vs2012的工具下的扩展工具 3.搜索nuget,没安装的直接在线安装 4.安装好了NuGet,程序包管理器控制台 5.执行命令Install-Package Enti ...