Editorial
Let be a vertex of the tree. Let's define:
as the maximum sum of coins that can be collected from the subtree rooted at if we take the coins in vertex .
as the maximum sum of coins that can be collected from the subtree rooted at if we do not take the coins in vertex .
Then the answer to the problem will be , assuming the first vertex is taken as the root of the tree.
Let’s define the given functions recursively:
If we take the coins in vertex , then we cannot take coins from its children:
If we do not take the coins in vertex , then we can choose either to take or not take coins from its children. We select the option with the maximum sum of coins:
If is a leaf with coins, then the functions take the following values: and .
Example
Let's assign the labels to the vertices of the trees from the examples.
For the first example, we have:
;
;
;
;
For the second example, we have:
;
;
;
;
Exercise
Assign the labels to the vertices of the tree:
Algorithm realization
Declare the arrays.
vector<vector<int> > g; vector<int> dp1, dp2, cost;
The dfs function implements depth-first search. Compute the values of and at all vertices of the tree.
void dfs(int v, int p = -1) { dp1[v] = cost[v]; dp2[v] = 0; for (int to : g[v]) { if (to == p) continue; dfs(to, v); dp1[v] += dp2[to]; dp2[v] += max(dp1[to], dp2[to]); } }
The main part of the program. Read the tree and the array of coins.
scanf("%d",&n); g.resize(n+1); for(i = 1; i < n; i++) { scanf("%d %d",&u,&v); g[u].push_back(v); g[v].push_back(u); } dp1.resize(n+1); dp2.resize(n+1); cost.resize(n+1); for(i = 1; i <= n; i++) scanf("%d",&cost[i]);
Let the root of the tree be at vertex . Start the depth-first search from there.
dfs(1);
Compute and print the answer.
ans = max(dp1[1], dp2[1]); printf("%d\n",ans);