Tree chain problemTime
limit:6000/3000 MS (java/others) Memory limit:65536/65536 K (java/others)
Total submission (s): 262 Accepted Submission (s): 59
Problem Descriptioncoco has a tree, whose vertices is conveniently labeled by,..., N.
There is m chain on the tree and each chain have a certain weight. Coco would like to pick out some chains any of the which does not share common vertices.
Find out the maximum sum of the weight Coco can pick
Inputthe 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, 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 end points and the weight of a T REE chain.
Outputfor each tests:
A single integer, the maximum number of paths.
Sample Input
17 31 21 32 42 53 63 72 3 44 5 36 7 3
Sample Output
6Hint
The main topic: there is a number of n nodes, give n-1 edge (no direction), there is a chain of M, each link two vertices (according to LCA Link), the chain exists a weight of W, now want to pick some chain, select the chain can not appear the same node, ask can be selected the maximum weight is how much?
The maximum weight is required, according to the idea of tree DP, then dp[i] is the optimal solution to the sub-tree of the root node of the first point. Dp[i] State transfer formula, there are two possibilities, the first: No chain on the node I, then Dp[i] =∑ (Dp[k] | K is the child of I); the second: A chain appears on the first node, and if you choose to join the chain, then dp[i] = W (weight of the chain) +∑ (dp[k) | K is the child node of the node on the chain ) = W +∑ (Sum[k] | K is the node on the chain )-∑ (Dp[k] | K is the node on the chain). Sum[i] represents the DP sum of all the child nodes of the I node, and the dp[k in the ∑ (Sum[k] | K for the node on the chain )-∑ (Dp[k] | K for the node in the chain) is the sum of its parent node. This gives the state transfer formula.
There is also an LCA to calculate the two vertices of the given chain (to update the DP value), the node on the chain (Sun's and) (DP's) is computed when the DP value is updated, the tree array is used to calculate, DFS for all nodes, the points are renumbered, Each point is reached and each departure point is numbered, recorded in L[i] and r[i], when calculated to play a sum[i] value, added to the tree array C1 (L[i] position plus positive, r[i] position plus negative), after calculating a dp[i] value, add to the tree array C2 (L[i] Position plus positive value, r[i] position plus negative), According to the new number of tree array to calculate the interval and, you can get the node on the chain and
Summarize:
1, achievements, topics given (no to the side), to add bilateral
2, DFS, establish the RMQ[I][J]:I node 2^j parent node, renumber the node
3, to the given two vertex to seek LCA, (code with RMQ for LCA)
4, the tree-like array, to find the interval and.
5, deep Search, complete the tree DP, according to the state transfer equation to calculate the value of each node, using a tree-like array to calculate the node on the chain and
#include <cstdio> #include <cstring> #include <vector> #include <algorithm>using namespace std; #pragma COMMENT (linker, "/stack:1024000000,1024000000") #define MAXN 200050struct e{int V, Next;} EDGE[MAXN]; int HEAD[MAXN], cnt; struct node{int u, V, W; int LCA;} P[MAXN]; int DEP[MAXN], rmq[maxn][20]; int l[100010], R[MAXN], CID, Vector <int> VEC[MAXN]; int DP[MAXN], sum[ma XN]; int C1[MAXN], C2[MAXN]; void add_e (int u,int v) {edge[cnt].v = v; Edge[cnt].next = Head[u]; Head[u] = cnt++; EDGE[CNT].V = u; Edge[cnt].next = Head[v]; HEAD[V] = cnt++;} void dfs (int fa,int u) {l[u] = ++cid; int I, j, V; for (i = head[u]; I! =-1; i = edge[i].next) {v = edge[i].v; if (v = = FA) continue; DEP[V] = Dep[u] + 1; Rmq[v][0] = u; for (j = 1; J <; J + +) Rmq[v][j] = rmq[rmq[v][j-1]][j-1]; DFS (U,V); } R[u] = ++cid;} int LCA (int u,int v) {if (Dep[u] < DEP[V]) swap (U,V); int I, J; for (i = n; I >= 0; i--) {if (dep[Rmq[u][i]] >= dep[v]) u = rmq[u][i]; if (U = = v) return u; } for (i = n; I >= 0; i--) {if (Rmq[u][i]! = Rmq[v][i]) {u = rmq[u][i]; v = rmq[v][i]; }} return rmq[u][0];} int lowbit (int x) {return x & x;} void Add (int i,int k,int *c,int N) {while (I <= N) {C[i] + = k; i + = Lowbit (i); }}int getsum (int i,int *c) {int ans = 0; while (i) {ans + = c[i]; I-= lowbit (i); } return ans; void Solve (int fa,int s,int n) {dp[s] = Sum[s] = 0; int I, J, u, V, temp; for (i = head[s]; I! =-1; i = edge[i].next) {v = edge[i].v; if (v = = FA) continue; Solve (s,v,n); Sum[s] + = Dp[v]; } Dp[s] = Sum[s]; for (i = 0; i < vec[s].size (); i++) {u = p[vec[s][i]].u; v = p[Vec[s][i]].V; temp = Getsum (L[U],C1) + getsum (L[V],C1)-Getsum (L[U],C2)-Getsum (L[V],C2) + sum[s]; Dp[s] = max (DP[S],TEMP+P[VEC[S][I]].W); } add (l[s],sum[s],c1,n*2); Add (r[s],-sum[s],c1,n*2); Add (l[s],dp[s],c2,n*2); Add (r[s],-dp[s],c2,n*2);} void init (int n) {memset (head,-1,sizeof (head)); memset (rmq,0,sizeof (RMQ)); Memset (C1,0,sizeof (C1)); memset (c2,0,sizeof (C2)); CNT = CID = 0; DEP[1] = 1; Rmq[1][0] = 1; for (int i = 1; I <= n; i++) vec[i].clear (); return;} int main () {int T, n, M; int I, J, U, V, W; Freopen ("1006.in", "R", stdin); Freopen ("T.out", "w", stdout); scanf ("%d", &t); while (t--) {scanf ("%d%d", &n, &m); Init (n); for (i = 1; i < n; i++) {scanf ("%d%d", &u, &v); Add_e (U,V); } dfs ( -1,1); for (i = 0; i < m; i++) {scanf ("%d%d%d", &p[i].u, &P[I].V, &P[I].W); P[I].LCA = LCA (P[I].U,P[I].V); vec[P[i].lca].push_back (i); } solve ( -1,1,n); printf ("%d\n", dp[1]); } return 0;}
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
HDU5293 (more than 2015 schools 1)--tree chain problem (tree-like DP)