Infected Tree#11724

Infected Tree (Editorial)

For each vertex , compute the number of vertices in the subtree where it is the root. If to_1, to_2, ..., to_k are the children of vertex , then

sum[v] = 1 + sum[to_1] + sum[to_2] + ... + sum[to_k]

If vertex is a leaf of the tree, then sum[v] = 1.

Let be the number of saved vertices in the subtree with root , assuming that currently vertex (and only it in the subtree) is infected.

If vertex has only one child , then dp[v] = sum[to] - 1 (the removed vertex is not considered saved).

Let vertex have two children to_1 and to_2 (each vertex has a degree of at most ). Then we have two options:

Among the two options, choose the one that maximizes the number of saved vertices.

Consider the depth-first search process when examining the edge (v, to).

Let be the second child of vertex . We need to compute the value dp[to] + sum[a] - 1. Let's try to find it using only the vertices and . We know that:

sum[v] = 1 + sum[to] + sum[a]

From which it follows that:

sum[a] = sum[v] - sum[to] - 1

Thus,

dp[to] + sum[a] - 1 = dp[to] + sum[v] - sum[to] - 2

Iterate over the children of the vertex and compute:

dp[v] = max(dp[to] + sum[v] - sum[to] - 2)

Example

In the first example, Huseyn is able to save two vertices, and , by choosing vertex number as his first move.|

Consider the second example. Next to each vertex , place the labels sum[v] / dp[v]. The vertices chosen by Huseyn are displayed in green.

For example,

dp[1] = max(sum[2] - 1 + dp[5], sum[5] - 1 + dp[2]) = max(2, 2) = 2, \\ sum[1] = 1 + sum[2] + sum[5] = 1 + 3 + 3 = 7

Algorithm implementation

Declare the arrays.

#define MAX 300005
int sum[MAX], dp[MAX];
vector<vector<int>> g;

The function dfs performs a depth-first search starting from vertex . The parent of vertex is .

void dfs(int v, int p = -1)
{

Initialize the variables and .

  sum[v] = 1;
  dp[v] = 0;

Perform a depth-first search starting from the children of vertex .

  for (int to : g[v])
    if (to != p)
    {
      dfs(to, v);
      sum[v] += sum[to];
    }

Compute the value of .

  for (int to : g[v])
    if (to != p)
    {
      dp[v] = max(dp[v], sum[to] - 1); // if 1 son
      dp[v] = max(dp[v], dp[to] + sum[v] - sum[to] - 2);
    }
}

The main part of the program. Read the input data.

scanf("%d", &n);
g.clear(); g.resize(n + 1);
memset(dp, 0, sizeof(dp));
memset(sum, 0, sizeof(sum));
for (i = 1; i < n; i++)
{
  scanf("%d %d", &u, &v);
  g[u].push_back(v);
  g[v].push_back(u);
}

Perform a depth-first search starting from vertex .

dfs(1);

Print the answer.

printf("%d\n", dp[1]);