Problem: 2063C - Remove Exactly Two
Language: c++17 

Solution 1 (runtime: 233 ms):
#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;
        vector<int> deg(n+1, 0);
 
        for (int i = 1; i <= n-1; i++){
            int u, v;
            cin >> u >> v;
            // Build the tree
            adj[u].push_back(v);
            adj[v].push_back(u);
            edges.push_back({u, v});
            deg[u]++;
            deg[v]++;
        }
 
        // Sort each adjacency list for binary search later
        for (int i = 1; i <= n; i++){
            sort(adj[i].begin(), adj[i].end());
        }
 
        // Best candidate from adjacent pairs:
        // For an edge (u,v) the value is deg(u)+deg(v)-2.
        int bestAdj = 0;
        for(auto &e : edges){
            int u = e.first, v = e.second;
            bestAdj = max(bestAdj, deg[u] + deg[v] - 2);
        }
 
        // Prepare list of vertices sorted by degree descending.
        // Each element is {degree, vertex}.
        vector<pair<int,int>> verts;
        verts.reserve(n);
        for (int i = 1; i <= n; i++){
            verts.push_back({deg[i], i});
        }
        sort(verts.begin(), verts.end(), [](auto &a, auto &b){
            return a.first > b.first;
        });
 
        int bestNonAdj = 0;
        // We'll iterate for each vertex in the top K (outer loop)
        // and for each such vertex, iterate over all vertices (inner loop)
        int K = min(n, 400);
        for (int i = 0; i < K; i++){
            int u = verts[i].second;
            int du = verts[i].first;
            // Early break: if even pairing u with the best possible partner can't beat bestNonAdj, we can skip.
            if(du + verts[0].first - 1 <= bestNonAdj) break;
            for (int j = 0; j < n; j++){
                int v = verts[j].second;
                if(v == u) continue;
                int candidate;
                // Check if u and v are adjacent using binary search.
                bool areAdj = false;
                if(adj[u].size() < adj[v].size()){
                    areAdj = binary_search(adj[u].begin(), adj[u].end(), v);
                } else {
                    areAdj = binary_search(adj[v].begin(), adj[v].end(), u);
                }
                if(areAdj)
                    candidate = du + verts[j].first - 2;
                else
                    candidate = du + verts[j].first - 1;
 
                bestNonAdj = max(bestNonAdj, candidate);
 
                // Early break inner loop if the maximum possible candidate with u
                // (i.e. du + current partner's degree - 1) is no better than bestNonAdj.
                if(du + verts[j].first - 1 <= bestNonAdj) break;
            }
        }
 
        int ans = max(bestAdj, bestNonAdj);
        cout << ans << "\n";
    }
    return 0;
}


Solution 2 (runtime: 733 ms):
#include <bits/stdc++.h>
#define ll long long
#define endl '\n'

using namespace std;


int n;
signed main() {
    ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);

    int t; cin >> t;

    while(t--) {
        cin >> n;

        vector<int> edge[n+1], cnt(n+1, 0);
        for (int i = 0; i < n-1; i++) {
            int u, v; cin >> u >> v;
            edge[u].push_back(v); cnt[u]++;
            edge[v].push_back(u); cnt[v]++;
        }

        multiset<int> ms;
        for (int i = 1; i <= n; i++) ms.insert(cnt[i]);

        int ans = 0;
        for (int i = 1; i <= n; i++) {
            ms.erase(ms.find(cnt[i]));
            for (auto e: edge[i]) ms.erase(ms.find(cnt[e])), ms.insert(cnt[e] - 1);
            ans = max(ans, *ms.rbegin() + cnt[i] - 1);
            ms.insert(cnt[i]);
            for (auto e: edge[i]) ms.erase(ms.find(cnt[e] - 1)), ms.insert(cnt[e]);
        }

        cout << ans << endl;
    }

    return 0;
}