Official

G - Erase Leaves Editorial by en_translator


Take a vertex remaining right after removing vertex \(1\) (or take vertex \(1\) if there is no such vertex), and regard the original tree rooted at that vertex.

Then, right before removing vertex \(1\), all the descendants of vertex \(1\) must be removed.

Conversely, by removing the descendants of vertex \(1\) from deeper one to shallower, the objective can be without removing all vertices but vertex \(1\) and its descendants, so the number of operations required equals the size of subtree rooted at \(1\).

Therefore, this problem is boiled down to finding the minimum size of the subtree rooted at \(1\) when the root of the original tree can be freely chosen. (By performing operations from deeper to shallower likewise, it turns out that we can choose any vertex and decide to retain it.)

If you remove vertex \(1\) and incident edges from the original tree, we obtain a forest. When a vertex (that is not vertex \(1\)) is taken as the root, the size of the subtree rooted at vertex \(1\) equals \(n\) subtracted by the size of the connected component that the vertex taken as the root belongs.

Hence, the sought minimum value equals \(n\) subtracted by the maximum size of the connected component of the forest.

The problem can be solved by implementing it. One can use a disjoint set union or perform a tree-DP (Dynamic Programming) from vertex \(1\).

The following is sample code.

#include <iostream>
#include <ranges>
#include <atcoder/dsu>

int main() {
    using namespace std;

    unsigned N;
    cin >> N;

    // For the forest resulting from removing vertex 1,
    // manage the connected component using disjoint set union
    atcoder::dsu forest(N);

    for (unsigned i = 1; i < N; ++i) {
        unsigned u, v;
        cin >> u >> v;
        if (u != 1) // If this edge is not incident to vertex 1,
            forest.merge(u - 1, v - 1); // add an edge
    }

    // The answer is N subtracted by the maximum size of a connected component
    cout << N - ranges::max(forest.groups() | views::transform([](auto &&g) { return size(g); })) << endl;

    return 0;
}

posted:
last update: