Maximum sum on a tree#973

Maximum sum on a tree (Editorial)

Let be a vertex of the tree. Let's define:

Then the answer to the problem will be max(dp_1(1), dp_2(1)), assuming the first vertex is taken as the root of the tree.

Let’s define the given functions recursively:

dp_1(v) = c_v + \sum_{i=1}^k dp_2(to_i), where~to_1, ..., to_k~are~the~sons~of~vertex~v.
dp_2(v) = \sum_{i=1}^k max(dp_1(to_i), dp_2(to_i)), where~to_1, ..., to_k~are~the~sons~of~vertex~v.

If is a leaf with c_v coins, then the functions take the following values: dp_1(v) = c_v and dp_2(v) = 0.

Example

Let's assign the labels dp_1(v) / dp_2(v) 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 dp_1(v) / dp_2(v) 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 dp_1 and dp_2 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);