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


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, then removing both vertices leaves an empty graph (0 components)
        if(n == 2){
            cout << 0 << "\n";
            continue;
        }
        
        // Compute degrees for each vertex.
        vector<int> deg(n+1, 0);
        for (int i = 1; i <= n; i++){
            deg[i] = adj[i].size();
        }
 
        // -------- Case: adjacent pairs --------
        // For every edge (which connects two adjacent vertices), the resulting number of components would be:
        //   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: non–adjacent pairs --------
        // For non-adjacent vertices u and v, the number of components would be:
        //   deg(u) + deg(v) - 1.
        // We want to find the maximum value of (deg(u)+deg(v)) among non-adjacent pairs.
        // We assume that the pair maximizing this sum will come from vertices with large degrees.
        // We take a candidate set: the top K vertices by degree.
        int candidateLimit = min(n, 300);
        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;
        });
 
        // Build candidate list (store vertex ids)
        vector<int> candVertices;
        for (int i = 0; i < candidateLimit; i++){
            candVertices.push_back(candidates[i].first);
        }
 
        // Build mapping from vertex to candidate index (for vertices in our candidate set).
        unordered_map<int,int> candIndex;
        for (int i = 0; i < candVertices.size(); i++){
            candIndex[candVertices[i]] = i;
        }
 
        int m = candVertices.size();
        // Create a 2D boolean matrix (m x m) to mark if two candidate vertices are adjacent.
        vector<vector<bool>> isAdj(m, vector<bool>(m, false));
        // For each candidate vertex, mark edges to other candidate vertices.
        for (int i = 0; i < m; i++){
            int v = candVertices[i];
            for (int nb : adj[v]){
                if(candIndex.count(nb)){
                    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);
                }
            }
        }
 
        // The answer is the best we can do among the two cases.
        int answer = max(bestAdjacent, bestNonAdjacent);
        cout << answer << "\n";
    }
    return 0;
}