1. Concise Problem Statement  
Given a tree of N nodes (1≤N≤16 000) with N–1 edges, define for each vertex k the size of the largest connected component remaining after removing k (and its incident edges). Find the minimum such size over all k, and list all vertices achieving it (the tree’s centroid(s)). Output the minimum size, the count of centroids, and the sorted list of centroids.

2. Detailed Editorial  
Definition and goal  
A centroid of a tree is a vertex whose removal breaks the tree into components, none larger than ⌈N/2⌉, and in particular minimizes the size of the largest remaining component. We must compute, for each node u, the value  
  val[u] = max( largest subtree size when u is removed )  
and then report the minimum val[u] and all u attaining it.

Key observations  
- Removing u splits the tree into deg(u) components, each hanging off one neighbor.  
- If we root the tree (say at 1), then for each node u and each child v in the rooted tree, removing u yields a component of size subtree_size[v].  
- Additionally, the “rest of the tree” above u (its parent side) forms a component of size N – subtree_size[u].  
- Therefore,  
    val[u] = max( N – subtree_size[u], max_over_children( subtree_size[child] ) ).

Algorithm outline  
1. Read N and the edges; build an adjacency list.  
2. Run a DFS from node 1 to compute subtree_size[u] for all u.  
3. For each u=1…N, compute:  
     up_size = N – subtree_size[u]  
     max_child = max( subtree_size[v] for v child of u )  
     val[u] = max(up_size, max_child)  
4. Scan val[1..N], find mn = min(val), collect all u with val[u]==mn.  
5. Output mn, count of centroids, and the sorted list of centroids.

Complexity  
- Time: O(N) for the DFS and one pass over nodes/edges.  
- Memory: O(N) for adjacency lists and auxiliary arrays.

3. C++ Solution
```cpp
#include <bits/stdc++.h>

using namespace std;

template<typename T1, typename T2>
ostream& operator<<(ostream& out, const pair<T1, T2>& x) {
    return out << x.first << ' ' << x.second;
}

template<typename T1, typename T2>
istream& operator>>(istream& in, pair<T1, T2>& x) {
    return in >> x.first >> x.second;
}

template<typename T>
istream& operator>>(istream& in, vector<T>& a) {
    for(auto& x: a) {
        in >> x;
    }
    return in;
};

template<typename T>
ostream& operator<<(ostream& out, const vector<T>& a) {
    for(auto x: a) {
        out << x << ' ';
    }
    return out;
};

int n;
vector<vector<int>> adj;
vector<int> tr_sz;

void read() {
    cin >> n;
    adj.assign(n + 1, {});
    for(int i = 0; i < n - 1; i++) {
        int u, v;
        cin >> u >> v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
}

void dfs(int u, int pr) {
    tr_sz[u] = 1;
    for(int v: adj[u]) {
        if(v != pr) {
            dfs(v, u);
            tr_sz[u] += tr_sz[v];
        }
    }
}

void solve() {
    /*
     * Centroid by subtree sizes. Root the tree at vertex 1 and compute tr_sz
     * via DFS. Removing vertex u leaves components: the "up" part of size
     * n - tr_sz[u], and one component per child v of size tr_sz[v]. The value
     * val[u] is the largest such component, i.e. max(n - tr_sz[u], max child
     * subtree). A neighbour v is a child iff tr_sz[v] < tr_sz[u] (its size is
     * smaller under this rooting). The centroids are all vertices attaining the
     * minimum val, listed in ascending order.
     */

    tr_sz.assign(n + 1, 0);
    dfs(1, 1);

    vector<int> val(n + 1, 0);
    int mn = n;
    for(int u = 1; u <= n; u++) {
        val[u] = n - tr_sz[u];
        for(int v: adj[u]) {
            if(tr_sz[v] < tr_sz[u]) {
                val[u] = max(val[u], tr_sz[v]);
            }
        }

        mn = min(mn, val[u]);
    }

    vector<int> li;
    for(int i = 1; i <= n; i++) {
        if(val[i] == mn) {
            li.push_back(i);
        }
    }

    cout << mn << " " << li.size() << '\n';
    for(int x: li) {
        cout << x << " ";
    }
    cout << '\n';
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    int T = 1;
    // cin >> T;
    for(int test = 1; test <= T; test++) {
        read();
        // cout << "Case #" << test << ": ";
        solve();
    }

    return 0;
}
```

4. Python Solution with Detailed Comments  
```python
import sys
sys.setrecursionlimit(1000000)

def main():
    data = sys.stdin.read().split()
    # Parse input
    it = iter(data)
    n = int(next(it))
    adj = [[] for _ in range(n+1)]
    for _ in range(n-1):
        u = int(next(it)); v = int(next(it))
        adj[u].append(v)
        adj[v].append(u)

    # Compute subtree sizes by DFS
    tr_sz = [0]*(n+1)
    def dfs(u, p):
        """Return size of subtree rooted at u, excluding parent p."""
        tr_sz[u] = 1
        for v in adj[u]:
            if v == p:
                continue
            dfs(v, u)
            tr_sz[u] += tr_sz[v]
        return tr_sz[u]

    dfs(1, 0)

    # Compute for each node the largest component size after removal
    val = [0]*(n+1)
    mn = n
    for u in range(1, n+1):
        # Component size of the “rest of the tree”
        max_comp = n - tr_sz[u]
        # For each neighbor v that is a child in the DFS tree,
        # its subtree becomes one component when removing u
        for v in adj[u]:
            if tr_sz[v] < tr_sz[u]:
                max_comp = max(max_comp, tr_sz[v])
        val[u] = max_comp
        if max_comp < mn:
            mn = max_comp

    # Collect centroids
    centroids = [u for u in range(1, n+1) if val[u] == mn]

    # Output results
    # First line: minimum largest component size and count of centroids
    print(mn, len(centroids))
    # Second line: sorted list of centroids
    print(*centroids)

if __name__ == "__main__":
    main()
```

5. Compressed Editorial  
Root the tree arbitrarily (e.g. at 1) and compute subtree sizes via DFS. For each node u, removing it yields one “upper” component of size N–subtree_size[u] and one component per child of size subtree_size[child]. The value val[u] is the maximum of these. The centroids are nodes minimizing val[u]. This runs in O(N) time and O(N) space.