树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)
题意:
有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(树链问题)的更多相关文章
- HDU 5293 Annoying problem 树形dp dfs序 树状数组 lca
Annoying problem 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 Description Coco has a tree, w ...
- 洛谷P3374 【模板】树状数组 1&&P3368 【模板】树状数组 2题解
图片来自度娘~~ 树状数组形如上图,是一种快速查找区间和,快速修改的一种数据结构,一个查询和修改复杂度都为log(n),树状数组1和树状数组2都是板子题,在这里进行详解: 求和: 首先我们看一看这个图 ...
- [HDU 5293]Tree chain problem(树形dp+树链剖分)
[HDU 5293]Tree chain problem(树形dp+树链剖分) 题面 在一棵树中,给出若干条链和链的权值,求选取不相交的链使得权值和最大. 分析 考虑树形dp,dp[x]表示以x为子树 ...
- HDU 5293 Tree chain problem 树形dp+dfs序+树状数组+LCA
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 题意: 给你一些链,每条链都有自己的价值,求不相交不重合的链能够组成的最大价值. 题解: 树形 ...
- HDU 5293 Train chain Problem - 树链剖分(树状数组) + 线段树+ 树型dp
传送门 题目大意: 一颗n个点的树,给出m条链,第i条链的权值是\(w_i\),可以选择若干条不相交的链,求最大权值和. 题目分析: 树型dp: dp[u][0]表示不经过u节点,其子树的最优值,dp ...
- 线段树(单点更新)/树状数组 HDOJ 1166 敌兵布阵
题目传送门 /* 线段树基本功能:区间值的和,修改某个值 */ #include <cstdio> #include <cstring> #define lson l, m, ...
- 树状数组 Binary Indexed Tree/Fenwick Tree
2018-03-25 17:29:29 树状数组是一个比较小众的数据结构,主要应用领域是快速的对mutable array进行区间求和. 对于一般的一维情况下的区间和问题,一般有以下两种解法: 1)D ...
- [bzoj1901][zoj2112][Dynamic Rankings] (整体二分+树状数组 or 动态开点线段树 or 主席树)
Dynamic Rankings Time Limit: 10 Seconds Memory Limit: 32768 KB The Company Dynamic Rankings has ...
- HDU 3436--Queue-jumpers (树状数组 or Splay Tree)
树状数组这个真心想了好久,还是没想出来 %%% www.cppblog.com/Yuan/archive/2010/08/18/123871.html 树状数组求前缀和大于等于k的最大值,第一次看到这 ...
随机推荐
- Android 数字签名
一个ApK如果要安装到手机上,必须要一个数字签名,不过你是debug也好,release也好,这个数字签名来源一个叫做证书的东西,在我们debug的时候,开发工具已经帮我们生成了一个叫做debug.k ...
- 【Unity3d】火炬之光的X射线效果
http://www.cnblogs.com/dosomething/archive/2012/04/03/2431149.html 人物和摄像机之间存在例如墙壁等的阻挡时 可以修改阻挡材质的alp ...
- input事件与change事件
输入框的change事件: 必须等到输入框失去焦点的时候才会触发,鼠标在空白的地方点一下: 输入框的input事件: 在输入内容变化的同时,实时的触发,不需要等到失去焦点.
- 用遗传算法GA改进CloudSim自带的资源调度策略(2)
遗传算法GA的核心代码实现: 最核心: private static ArrayList<int[]> GA(ArrayList<int[]> pop,int gmax,dou ...
- Google Code Jam 2016 Round 1C C
题意:三种物品分别有a b c个(a<=b<=c),现在每种物品各选一个进行组合.要求每种最和最多出现一次.且要求任意两个物品的组合在所有三个物品组合中的出现总次数不能超过n. 要求给出一 ...
- Mosquitto搭建Android推送服务(一)MQTT简介
总体概要: MQTT系列文章分为4部分 1.MQTT简介 2.mosquitto服务器搭建 3.编写Mosquitto的可视化工具 4.使用Mosquitto完成Android推送服务 文章钢要: 对 ...
- iOS 局部变量 全局变量 成员变量
一.成员变量 : 写在类声明的大括号中的变量叫成员变量 (也叫属性/实例变量) 成员变量不可离开类 离开了类就不是成员变量 成员变量不能再定义的同事初始化 成员量只能通过对象来访问 成员变量存储在堆中 ...
- extern
gcc编译器编译程序有四个阶段,预处理.编译.汇编.链接.预处理阶段会将源代码中的包含的头文件如stdio.h编译进来:编译阶段,gcc首先要检查代码的规范性.是否有语法错误等,以确定代码的实际要做的 ...
- 【mongo】聚合相关资料
一个很好的博客:http://www.cnblogs.com/shanyou/p/3494854.html 官网:https://docs.mongodb.com/manual/reference/o ...
- iOS url中文编码
有两种方法: 一,使用NSString的方法: NSString* string2 = [string1 stringByAddingPercentEscapesUsingEncoding:NSUTF ...