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

Solution 1 (runtime: 406 ms):
/**
 * SUGESTAO abaixo
 * A minha passava por trabalhar directamente com graus de saida ordenados
 * de forma decrescente, esbarrando com TLE na forma de optimizar o processamento
 * dos filhos apenas entre nos com maior grau de saida
 */

#include <bits/stdc++.h>
#define BOOST ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define ll long long

using namespace std;
 
int main(){
    BOOST
    
    int t;
    cin >> t;
    while(t--){
        int N;
        cin >> N;
        
        // Arvore
        vector<vector<int>> g(N+1);
        vector<int> deg(N+1, 0);        // graus de saida
        for (int i = 1; i <= N-1; i++){
            int u, v;
            cin >> u >> v;
            // Tomar arvore como grafo nao dirigido
            g[u].push_back(v);
            g[v].push_back(u);
            deg[u]++;
            deg[v]++;
        }
        
        // Build an adjacency checker (for O(1) adjacent queries).
        vector<unordered_set<int>> adj(N+1);
        for (int u = 1; u <= N; u++){
            for (int nb : g[u]){
                adj[u].insert(nb);
            }
        }
        
        // Calculo do grau maximo
        int max_deg = 0;
        for (int u = 1; u <= N; u++){
            max_deg = max(max_deg, deg[u]);
        }
        
        // Juntar pelo menos dois vertices com o grau maximo
        vector<int> max_nodes;
        for (int u = 1; u <= N; u++){
            if (deg[u] == max_deg)
                max_nodes.push_back(u);
        }
        // Basta dois vertices de grau maximo (caso haja empate entre mais de 2 com o grau maximo)
        if (max_nodes.size() > 2)
            max_nodes.resize(2);
        
        int ans = 0;
        // Para cada maximo tentar outro no
        for (int node : max_nodes) {
            for (int v = 1; v <= N; v++){
                if (v == node) continue;        // saltar o no em analise
                int n_val;
                // Se forem nos adjacentes subratir 1, senao subtrair 2 para obter o num de componentes
                if (adj[node].find(v) != adj[node].end()){
                    n_val = deg[node] + deg[v] - 2;
                } else {
                    n_val = deg[node] + deg[v] - 1;
                }
                ans = max(ans, n_val);
            }
        }
        
        cout << ans << "\n";
    }
    return 0;
}


Solution 2 (runtime: 358 ms):

// Radhe Radhe !!!

/*/<------Author: KALKI_P----->/*/

#include<bits/stdc++.h>

// GNU Policy-Based Data Structures
#include <ext/pb_ds/assoc_container.hpp> 
#include <ext/pb_ds/tree_policy.hpp> 

using namespace std;
using namespace __gnu_pbds;
 
/*/---------------------------Defines----------------------/*/
#define all(x) (x).begin(), (x).end()
#define allr(x) (x).rbegin(), (x).rend()
#define sz(x) ((int)x.size())
 
#define ll long long
#define ld long double
#define endl '\n'
#define pb push_back

/*/<--------------------Modular Arithmetic---------------->/*/
const int mod = 1e9 + 7;
const ll inf = 1e18;
const int maxn = 1e5 + 5;

/*/<--------------------Template-------------------->/*/
// Ordered set functions
template <typename T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>; 

/*/<----------------------------NOTE----------------------->/*/

// Read the problem carefully
// Try to find the idea behind the problem
// Have a rough roadmap for the solution u will be going to implement 
// Once u have the roadmap for solution, implement it 

// If that implementation failed then repeat,

/*/<----------------------------Code Begins----------------------->/*/

long long binpow(long long a, long long b, long long m) {
    a %= m;
    long long res = 1;
    while (b > 0) {
        if (b & 1)
            res = res * a % m;
        a = a * a % m;
        b >>= 1;
    }
    return res;
}

struct DSU{

    vector<ll> parent, rank, size;

    DSU(ll n){
        rank.resize(n+1,0);parent.resize(n+1);size.resize(n+1);
        for(ll i=0;i<=n;i++)
        {
            parent[i] = i;
            size[i] = 1;
        }
    }

    ll findUPar(ll node){
        if(node == parent[node]) return node;
        return parent[node] = findUPar(parent[node]);
    }

    void UBR(ll u, ll v){
        ll ul_u = findUPar(u);
        ll ul_v = findUPar(v);

        if(ul_u == ul_v) return;
        else if(rank[ul_u] < rank[ul_v]){
            parent[ul_u] = ul_v;
        }
        else if(rank[ul_v] < rank[ul_u]){
            parent[ul_v] = ul_u;
        }
        else{
            parent[ul_u] = ul_v;
            rank[ul_v]++;
        }
    }

    void UBS(ll u, ll v){
        ll ul_u = findUPar(u);
        ll ul_v = findUPar(v);

        if(ul_u == ul_v) return;
        else if(size[ul_u] < size[ul_v]){
            parent[ul_u] = ul_v;
            size[ul_v] += size[ul_u];
        }
        else{
            parent[ul_v] = ul_u;
            size[ul_u] += size[ul_v];
        }
    }
};

void dfs(ll node, vector<ll> &vis, vector<set<ll>> &adj) {
    vis[node] = 1;
    for(auto it : adj[node]) {
        if(!vis[it]) {
            dfs(it, vis, adj);
        }
    }
}
 
void solve () {
    
    ll n; cin >> n;
    vector<set<ll>> adj(n+1);
    for(ll i = 0; i < n - 1; i++) {
        ll u, v; cin >> u >> v;
        adj[u].insert(v);
        adj[v].insert(u);
    }
    vector<pair<ll,ll>> max_adj;
    for(ll i = 1; i <= n; i++) {
        max_adj.push_back({adj[i].size(), i});
    }

    sort(allr(max_adj));

    ll node1 = max_adj[0].second, node2 = max_adj[1].second;
    if(adj[node1].find(node2) != adj[node1].end() && max_adj[0].first > max_adj[1].first) {
        ll maxi = max_adj[1].first;
        for(ll i = 2; i < n; i++) {
            if(max_adj[i].first == maxi) {
                if(adj[node1].find(max_adj[i].second) == adj[node1].end()) {
                    node2 = max_adj[i].second;
                    break;
                }
                else continue;
            }
        }
    }
    else if(adj[node1].find(node2) != adj[node1].end() && max_adj[0].first == max_adj[1].first) {
        ll val = max_adj[1].first;
        for(ll i = 2; i < n; i++) {
            if(max_adj[i].first == val) {
                if(adj[node1].find(max_adj[i].second) == adj[node1].end()) {
                    node2 = max_adj[i].second;
                    break;
                }
                else if(adj[node2].find(max_adj[i].second) == adj[node2].end()) {
                    node1 = max_adj[i].second;
                    break;
                }
                else continue;
            }
        }
    }

    vector<ll> vis(n+1, 0);
    vis[node1] = 1;
    vis[node2] = 1;

    // cout <<node1 << " : " << node2 << endl;

    ll cnt = 0;
    for(ll i = 1; i <= n; i++) {
        if(!vis[i]) {
            cnt++;
            dfs(i, vis, adj);
        }
    }

    cout << cnt << endl;

}

int main() {
    ios_base::sync_with_stdio(false); cin.tie(NULL);
    int ti = 1;  
    cin >> ti;

    // cout<<fixed<<setprecision(9);
    while (ti--) {
        solve();
    }
    return 0;
 
}