Problem: 2063C - Remove Exactly Two
Language: C++23 (GCC 14-64, msys2)

Previous submission (verdict: Wrong answer on test 12):
#include <bits/stdc++.h>
using namespace std;
 
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int t; 
    cin >> t;
    while(t--){
        int n;
        cin >> n;
        vector<vector<int>> adj(n+1);
        vector<pair<int,int>> edges;
        for (int i = 1; i <= n-1; i++){
            int u, v;
            cin >> u >> v;
            adj[u].push_back(v);
            adj[v].push_back(u);
            edges.push_back({u, v});
        }
        
        // Special case: if n == 2, removing both vertices gives an empty graph (0 components).
        if(n == 2){
            cout << 0 << "\n";
            continue;
        }
        
        // Compute degree for each vertex.
        vector<int> deg(n+1, 0);
        for (int i = 1; i <= n; i++){
            deg[i] = adj[i].size();
        }
 
        // ---------- Case 1: Adjacent pairs ----------
        // For an edge (u,v) (i.e. adjacent pair), the resulting components count is:
        //    deg(u) + deg(v) - 2.
        int bestAdjacent = 0;
        for(auto &e : edges){
            int u = e.first, v = e.second;
            bestAdjacent = max(bestAdjacent, deg[u] + deg[v] - 2);
        }
 
        // ---------- Case 2: Non-adjacent pairs ----------
        // For non-adjacent vertices u and v, the count is: deg(u) + deg(v) - 1.
        // We want the maximum such sum. It is expected that the best pair involves vertices with high degree.
        // To speed things up, we pick a candidate set of vertices (by degree).
        int candidateLimit = min(n, 1000);  // increased candidate limit to 1000 to avoid missing some cases
        vector<pair<int,int>> candidates; // pair: (vertex, degree)
        for (int i = 1; i <= n; i++){
            candidates.push_back({i, deg[i]});
        }
        sort(candidates.begin(), candidates.end(), [](auto &a, auto &b){
            return a.second > b.second;
        });
 
        vector<int> candVertices;
        for (int i = 0; i < candidateLimit; i++){
            candVertices.push_back(candidates[i].first);
        }
 
        // Build a mapping from vertex id to candidate index (for vertices in our candidate set).
        unordered_map<int,int> candIndex;
        for (int i = 0; i < (int)candVertices.size(); i++){
            candIndex[candVertices[i]] = i;
        }
 
        int m = candVertices.size();
        // Build a small m x m boolean matrix to quickly check if two candidate vertices are adjacent.
        vector<vector<bool>> isAdj(m, vector<bool>(m, false));
        for (int i = 0; i < m; i++){
            int v = candVertices[i];
            for (int nb : adj[v]){
                if(candIndex.find(nb) != candIndex.end()){
                    int j = candIndex[nb];
                    isAdj[i][j] = true;
                    isAdj[j][i] = true;
                }
            }
        }
 
        int bestNonAdjacent = 0;
        for (int i = 0; i < m; i++){
            for (int j = i+1; j < m; j++){
                if(!isAdj[i][j]){
                    int u = candVertices[i];
                    int v = candVertices[j];
                    bestNonAdjacent = max(bestNonAdjacent, deg[u] + deg[v] - 1);
                }
            }
        }
 
        int answer = max(bestAdjacent, bestNonAdjacent);
        cout << answer << "\n";
    }
    return 0;
}


Submission (verdict: Accepted):
#include <bits/stdc++.h>
using namespace std;
 
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
 
    int t;
    cin >> t;
    while(t--){
        int n;
        cin >> n;
        vector<vector<int>> adj(n+1);
        vector<pair<int,int>> edges;
        for(int i = 1; i <= n-1; i++){
            int u, v;
            cin >> u >> v;
            adj[u].push_back(v);
            adj[v].push_back(u);
            edges.push_back({u,v});
        }
 
        // Special case: if n == 2, then removing both vertices yields an empty graph (0 components).
        if(n == 2){
            cout << 0 << "\n";
            continue;
        }
 
        // Compute degree for each vertex.
        vector<int> deg(n+1, 0);
        for (int u = 1; u <= n; u++){
            deg[u] = adj[u].size();
        }
 
        // --- Case 1: Adjacent pairs ---
        // For an edge {u,v} (i.e. for adjacent vertices) the resulting number of components is:
        //   deg(u) + deg(v) - 2.
        int bestAdjacent = 0;
        for(auto &e : edges){
            int u = e.first, v = e.second;
            bestAdjacent = max(bestAdjacent, deg[u] + deg[v] - 2);
        }
 
        // --- Case 2: Non-adjacent pairs ---
        // For non-adjacent vertices u and v the components count is:
        //   deg(u) + deg(v) - 1.
        // We want to maximize d[u] + d[v] over all pairs (u,v) with u and v non–adjacent.
 
        // Build a global list L of vertices sorted in descending order by degree.
        vector<int> sorted(n);
        for (int i = 0; i < n; i++){
            sorted[i] = i+1;
        }
        sort(sorted.begin(), sorted.end(), [&](int a, int b){
            return deg[a] > deg[b];
        });
 
        // For fast membership queries we build, for each vertex, a set of its neighbors.
        vector<unordered_set<int>> forb(n+1);
        for (int u = 1; u <= n; u++){
            // Reserve a little extra space
            forb[u].reserve(adj[u].size() + 1);
            // Mark u itself as forbidden.
            forb[u].insert(u);
            for (int v : adj[u]){
                forb[u].insert(v);
            }
        }
 
        int bestNonAdjSum = 0; // will store max { deg(u)+deg(v) } for u,v non–adjacent.
        // For each vertex u, we try to find a vertex v (from our global sorted order) that is not in u's forbidden set.
        for (int u = 1; u <= n; u++){
            for (int v : sorted) {
                if (forb[u].find(v) == forb[u].end()){
                    bestNonAdjSum = max(bestNonAdjSum, deg[u] + deg[v]);
                    break; // v is the highest-degree vertex available for u.
                }
            }
        }
        // For non–adjacent pair, our value is (deg(u)+deg(v)-1)
        int bestNonAdjacent = (bestNonAdjSum == 0 ? 0 : bestNonAdjSum - 1);
 
        int ans = max(bestAdjacent, bestNonAdjacent);
        cout << ans << "\n";
    }
    return 0;
}