HDU5293(SummerTrainingDay13-B Tree DP + 树状数组 + dfs序)

Tree chain problem

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1798    Accepted Submission(s): 585

Problem Description

Coco has a tree, whose vertices are conveniently labeled by 1,2,…,n.
There are m chain on the tree, Each chain has a certain weight. Coco would like to pick out some chains any two of which do not share common vertices.
Find out the maximum sum of the weight Coco can pick

Input

The input consists of several test cases. The first line of input gives the number of test cases T (T<=10).
For each tests: 
First line two positive integers n, m.(1<=n,m<=100000)
The following (n - 1) lines contain 2 integers ai bi denoting an edge between vertices ai and bi (1≤ai,bi≤n),
Next m lines each three numbers u, v and val(1≤u,v≤n,0<val<1000), represent the two end points and the weight of a tree chain.

Output

For each tests:
A single integer, the maximum number of paths.

Sample Input

1
7 3
1 2
1 3
2 4
2 5
3 6
3 7
2 3 4
4 5 3
6 7 3

Sample Output

6

Hint

Stack expansion program: #pragma comment(linker, "/STACK:1024000000,1024000000")

Author

FZUACM

Source

2015 Multi-University Training Contest 1

对于每条链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])。

  1 //2017-09-13
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <iostream>
  5 #include <algorithm>
  6 #include <vector>
  7 #pragma comment(linker, "/STACK:1024000000,1024000000")
  8
  9 using namespace std;
 10
 11 const int N = 210000;
 12 const int LOG_N = 22;
 13
 14 int head[N], tot;
 15 struct Edge{
 16     int v, next;
 17 }edge[N<<1];
 18
 19 void add_edge(int u, int v){
 20     edge[tot].v = v;
 21     edge[tot].next = head[u];
 22     head[u] = tot++;
 23 }
 24
 25 int in[N], out[N], idx, depth[N], father[N][LOG_N];
 26 void dfs(int u, int fa){
 27     in[u] = ++idx;
 28     for(int i = head[u]; i != -1; i = edge[i].next){
 29         int v = edge[i].v;
 30         if(v == fa)continue;
 31         depth[v] = depth[u]+1;
 32         father[v][0]= u;
 33         for(int j = 1; j < LOG_N; j++)
 34           father[v][j] = father[father[v][j-1]][j-1];
 35         dfs(v, u);
 36     }
 37     out[u] = ++idx;
 38 }
 39
 40 int tree[N];
 41
 42 int lowbit(int x){
 43     return x&(-x);
 44 }
 45
 46 void add(int pos, int val){
 47     for(int i = pos; i <= N; i+=lowbit(i))
 48       tree[i] += val;
 49 }
 50
 51 int query(int l){
 52     int sum = 0;
 53     for(int i = l; i > 0; i-=lowbit(i))
 54       sum += tree[i];
 55     return sum;
 56 }
 57
 58 int lca(int u, int v){
 59     if(depth[u] < depth[v])
 60       swap(u, v);
 61     for(int i = LOG_N-1; i >= 0; i--){
 62         if(depth[father[u][i]] >= depth[v])
 63           u = father[u][i];
 64     }
 65     if(u == v)return u;
 66     for(int i = LOG_N-1; i >= 0; i--){
 67         if(father[u][i] != father[v][i]){
 68             u = father[u][i];
 69             v = father[v][i];
 70         }
 71     }
 72     return father[u][0];
 73 }
 74 struct Chain{
 75     int u, v, w;
 76 }chain[N];
 77 vector<int> vec[N];
 78
 79 int dp[N], sum[N];
 80 void solve(int u, int fa){
 81     dp[u] = sum[u] = 0;
 82     for(int i = head[u]; i != -1; i = edge[i].next){
 83         int v = edge[i].v;
 84         if(v == fa)continue;
 85         solve(v, u);
 86         sum[u] += dp[v];
 87     }
 88     dp[u] = sum[u];
 89     for(auto &pos: vec[u]){
 90         int a = chain[pos].u;
 91         int b = chain[pos].v;
 92         int c = chain[pos].w;
 93         dp[u] = max(dp[u], sum[u]+query(in[a])+query(in[b])+c);
 94     }
 95     add(in[u], sum[u]-dp[u]);
 96     add(out[u], dp[u]-sum[u]);
 97 }
 98
 99 int T, n, m;
100 void init(){
101     tot = 0;
102     idx = 0;
103     depth[1] = 1;
104     for(int i = 1; i <= n; i++)
105       vec[i].clear();
106     memset(head, -1, sizeof(head));
107     memset(dp, 0, sizeof(0));
108     memset(sum, 0, sizeof(0));
109     memset(tree, 0, sizeof(tree));
110 }
111
112 int main()
113 {
114     freopen("inputB.txt", "r", stdin);
115     scanf("%d", &T);
116     while(T--){
117         scanf("%d%d", &n, &m);
118         init();
119         int u, v;
120         for(int i = 0; i < n-1; i++){
121             scanf("%d%d", &u, &v);
122             add_edge(u, v);
123             add_edge(v, u);
124         }
125         dfs(1, 0);
126         for(int i = 0; i < m; i++){
127             scanf("%d%d%d", &chain[i].u, &chain[i].v, &chain[i].w);
128             vec[lca(chain[i].u, chain[i].v)].push_back(i);
129         }
130         solve(1, 0);
131         printf("%d\n", dp[1]);
132     }
133
134     return 0;
135 }
时间: 2024-10-10 03:26:09

HDU5293(SummerTrainingDay13-B Tree DP + 树状数组 + dfs序)的相关文章

【BZOJ】2434: [Noi2011]阿狸的打字机 AC自动机+树状数组+DFS序

[题意]阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的: l 输入小写字母,打字机的一个凹槽中会加入这个字母(这个字母加在凹槽的最后). l 按一下印有'B'的按键,打字机凹槽中最后一个字母会消失. l 按一下印有'P'的按键,打字机会在纸上打印出凹槽中现有的所有字母并换行,但凹槽中的字母不会消失. 我们把纸上打印出来的字符串从1开始顺序编号,一直到n.打字机有一个非

UCF Local Programming Contest 2018 E题(树状数组+dfs序)

如果这道题没有一个限制,那么就是一道树状数组+dfs序的裸题 第一个请求或许会带来困惑,导致想要动态建树,如果真的动态修改树,那么dfs序必定会改变,很难维护,并且数据很大,暴力应该会T 所以不妨先把全部的节点建好,这样只需要求一次dfs序,而对于第一种操作 我们只需要再那个位置减去在他之前的dfs序的bouns求和,并在这个的后一个位置+回来,这样就有这个点被修改,并且成为了一个新点,等同于要求的操作 #include<iostream> #include<cstdio> #in

codeforces 570 D. Tree Requests 树状数组+dfs搜索序

链接:http://codeforces.com/problemset/problem/570/D D. Tree Requests time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output Roman planted a tree consisting of n vertices. Each vertex contains a low

E - Apple Tree(树状数组+DFS序)

There is an apple tree outside of kaka's house. Every autumn, a lot of apples will grow in the tree. Kaka likes apple very much, so he has been carefully nurturing the big apple tree. The tree has N forks which are connected by branches. Kaka numbers

【BZOJ-1103】大都市meg 树状数组 + DFS序

1103: [POI2007]大都市meg Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2009  Solved: 1056[Submit][Status][Discuss] Description 在经济全球化浪潮的影响下,习惯于漫步在清晨的乡间小路的邮递员Blue Mary也开始骑着摩托车传递邮件了.不过,她经常回忆起以前在乡间漫步的情景.昔日,乡下有依次编号为1..n的n个小村庄,某些村庄之间有一些双向的土路.从每个村庄都恰好有一条路径到

BZOJ2434 NOI2011 阿狸的打字机 AC自动机+树状数组+DFS序

题意:给定三个操作:1.在当前字符串的末尾添加一个字符c  2.在当前字符串的末尾删除一个字符  3.记录当前字符串并对其标号.再给出N组询问,每组询问需回答第x个字符串在第y个字符串中出现的次数 题解: 首先按照如下规则建Trie,设当前节点为t,第i个字符串的结尾在Trie中的位置为mark[i]: 1.插入操作:看t是否有c这个儿子,有则t=t->child[c],否则t->child[c]=NewNode,t=t->child[c] 2.删除操作:t=t->father 3

BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]

2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2545  Solved: 1419[Submit][Status][Discuss] Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现,这个打字机是这样工作的:l 输入小写字母,打字机的一个凹槽中会加入这个字母(这个字母加在凹槽的最

[BZOJ 2434][Noi2011]阿狸的打字机(AC自动机+树状数组+dfs序)

Description 打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现,这个打字机是这样工作的: ·输入小写字母,打字机的一个凹槽中会加入这个字母(这个字母加在凹槽的最后). ·按一下印有'B'的按键,打字机凹槽中最后一个字母会消失. ·按一下印有'P'的按键,打字机会在纸上打印出凹槽中现有的所有字母并换行,但凹槽中的字母不会消失. 例如,阿狸输入aPaPBbP,纸上被打印的字符如下: a aa ab 我们把纸上打印出来的字符串从1开始顺序编号,一直到

【BZOJ3653】谈笑风生 离线+树状数组+DFS序

[BZOJ3653]谈笑风生 Description 设T 为一棵有根树,我们做如下的定义: ? 设a和b为T 中的两个不同节点.如果a是b的祖先,那么称“a比b不知道高明到哪里去了”. ? 设a 和 b 为 T 中的两个不同节点.如果 a 与 b 在树上的距离不超过某个给定常数x,那么称“a 与b 谈笑风生”. 给定一棵n个节点的有根树T,节点的编号为1 到 n,根节点为1号节点.你需要回答q 个询问,询问给定两个整数p和k,问有多少个有序三元组(a;b;c)满足: 1. a.b和 c为 T