Problem: 2063C - Remove Exactly Two
Language: C++17 (GCC 7-32)

Previous submission (verdict: Wrong answer on test 2):
#include <bits/stdc++.h>
using namespace std;

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
//			सुखदुःखे समे कृत्वा लाभालाभौ जयाजयौ॥
//			ततो युद्धाय युज्यस्व नैवं पापमवाप्स्यसि॥
template <typename T, class C = std::less<T>>
using ordered_set = tree<T, null_type, C, rb_tree_tag, tree_order_statistics_node_update>;

template <typename T, class C = std::less_equal<T>>
using ordered_multiset = tree<T, null_type, C, rb_tree_tag, tree_order_statistics_node_update>;

struct custom_hash {
    static uint64_t splitmix64(uint64_t x) {
// http://xorshift.di.unimi.it/splitmix64.c
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }

    size_t operator()(uint64_t x) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(x + FIXED_RANDOM);
    }
};

#define rep(i, begin, end) for (__typeof(end) i = (begin) - ((begin) > (end)); i != (end) - ((begin) > (end)); i += 1 - 2 * ((begin) > (end)))

#define int            long long int
#define F              first
#define S              second
#define pb             push_back
#define si             std::set <int>
#define vi             std::vector <int>
#define vvi            std::vector <vector <int>>
#define pii            std::pair <int, int>
#define vpi            std::vector <pii>
#define vpp            std::vector <pair<int, pii>>
#define umii           std::unordered_map <int, int, custom_hash>
#define mii            std::map <int, int>
#define mpi            std::map <pii, int>
#define spi            std::set <pii>
#define endl "\n"
#define sz(x)          ((int) x.size())
#define all(p)         p.begin(), p.end()
#define double         long double
#define que_max        std::priority_queue <int>
#define que_min        std::priority_queue <int, vi, greater<int>>
// https://stackoverflow.com/questions/2620862/using-custom-stdset-comparator
class compare{
    bool operator()(pair<int,int> below,pair<int,int> above){
        return above < below;
    }
};
// priority_queue<pair<int,int>, vector<pair<int,int>>, compare) > pq; // custom hash for pq
#define bug(...)       __f (#__VA_ARGS__, __VA_ARGS__)
template <typename T, typename S> constexpr T ifloor(const T a, const S b) { return a / b - (a % b && (a ^ b) < 0); }
template <typename T, typename S> constexpr T iceil(const T a, const S b) { return ifloor(a + b - 1, b); }
void setIO(string name = "") {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    if (!name.empty()) {
        freopen((name + ".in").c_str(), "r", stdin);
        freopen((name + ".out").c_str(), "w", stdout);
    }
}

#define set_bits __builtin_popcountll
#define lead_zero __builtin_clzll
#define trail_zero __builtin_ctzll

int nxt() {
    int x;
    std::cin >> x;
    return x;
}

int pow(int base, int exp) {
    int res = 1;
    while (exp > 0) {
        if (exp & 1)
            res = res * base;
        base = base * base;
        exp /= 2;
    }
    return res;
}

int pow(int base, int exp, int mod) {
    int res = 1;
    while (exp > 0) {
        if (exp & 1)
            res = (res * base) % mod;
        base = (base * base) % mod;
        exp /= 2;
    }
    return res;
}

const int mod = 1000000007;
const int N = 2e5 + 5;
//////////////////////////// PNC ////////////////////////////
vi fac, inv_fac;

void precompute_factorials(int n) {
    fac.resize(n+1,1);
    inv_fac.resize(n+1,1);
    for (int i = 1; i <= n; i++) fac[i] = (fac[i-1]*i)%mod;
    inv_fac[n] = pow(fac[n], mod-2, mod);
    for (int i = n-1; i >= 0; i--) inv_fac[i] = (inv_fac[i+1]*(i+1))%mod;
}

int C(int n, int k){
    if(n>=k && k>=0){
        int ret = (fac[n] * inv_fac[k]) % mod;
        ret = (ret * inv_fac[n-k]) % mod;
        return ret;
    }else{
        return 0;
    }
}
////////////////////////////////////////////////////////////

///////////////////////////// DSU ////////////////////////////
class DisjointSets {
    private:
    vector<int> parents;
    vector<int> sizes;

    public:
    DisjointSets(int size) : parents(size), sizes(size, 1) {
        for (int i = 0; i < size; i++) parents[i] = i;
    }

    int find(int x) { return parents[x] == x ? x : (parents[x] = find(parents[x])); }

    bool unite(int x, int y) {
        int x_root = find(x);
        int y_root = find(y);
        if (x_root == y_root) { return false; }

        if (sizes[x_root] < sizes[y_root]) { swap(x_root, y_root); }
        sizes[x_root] += sizes[y_root];
        parents[y_root] = x_root;
        return true;
    }

    bool connected(int x, int y) { return find(x) == find(y); }
};
///////////////////////////////////////////////////////

///////////////////////////// SEGMENT TREE ////////////////////////////
struct Node{
    int val;
    Node(){
        val = 0;
    }

    Node(int p1){
        val = p1;
    }

    void merge(Node &l, Node &r){
        val = __gcd(l.val, r.val);
    }
};

struct SegTree {
    vector<Node> tree;
    vi arr; // type may change
    int n;
    int s;
    SegTree(int a_len, vi &a){ // change if type updated
        arr = a;
        n = a_len;
        s = 1;
        while (s < 2 * n){
            s = s << 1;
        }
        tree.resize(s);
        fill(tree.begin(), tree.end(), Node());
        build(0, n - 1, 1);
    }
    void build(int start, int end, int index){ // Never change this
        if (start == end){
            tree[index] = Node(arr[start]);
            return;
        }
        int mid = (start + end) / 2;
        build(start, mid, 2 * index);
        build(mid + 1, end, 2 * index + 1);
        tree[index].merge(tree[2 * index], tree[2 * index + 1]);
    }
    Node query(int start, int end, int index, int left, int right){ // Never change this
        if (start > right || end < left) return Node();
        if (start >= left && end <= right) return tree[index];
        int mid = (start + end) / 2;
        Node l, r, ans;
        l = query(start, mid, 2 * index, left, right);
        r = query(mid + 1, end, 2 * index + 1, left, right);
        ans.merge(l, r);
        return ans;
    }
    Node make_query(int left, int right){
        return query(0, n - 1, 1, left, right);
    }
};
///////////////////////////////////////////////////////

void solve(){
    int n = nxt();
    vector<si> g(n);

    rep(i,0,n-1){
        int u = nxt()-1, v = nxt()-1;
        g[u].insert(v);
        g[v].insert(u);
    }
    auto check = [&](){
        int h = 0;
        queue<int> q;
        vector<bool> vis(n);
        mii m;
        rep(i,0,n){
            if(sz(g[i]) == 1){
                q.push(i);
                vis[i] = true;
            }
        }
        while(!q.empty()){
            int s = sz(q);
            h++;
            while(s--){
                int u = q.front();
                q.pop();
                m[u] = h;
                vis[u] = true;
                for(auto v: g[u]){
                    if(vis[v]) continue;
                    q.push(v);
                }
            }
        }
        int node = 0;
        rep(i,1,n){
            if(sz(g[i]) > sz(g[node])) node = i;
            else if(sz(g[i]) == sz(g[node]) && m[i] < m[node]) node = i;
        }
        return node;
    };

    int x = check();
    for(auto i: g[x]) g[i].erase(x);
    g[x].clear();

    int y = check();
    for(auto i: g[y]) g[i].erase(y);
    g[y].clear();

    int res = 0;
    vector<bool> vis(n, false);
    rep(i,0, n){
        if(vis[i]) continue;
        queue<int> q;
        q.push(i);
        res++;
        vis[i] = true;
        while(!q.empty()){
            int u = q.front();
            q.pop();
            for(auto v: g[u]){
                if(!vis[v]){
                    vis[v] = true;
                    q.push(v);
                }
            }
        }
    }
    std::cout<<res-2<<endl;
}

int32_t main() {
    setIO();
    //std::cout<<std::fixed<<std::setprecision(0);
    //set_factorial(N+1);
    int t=1;
    std::cin>>t;
    while(t--) solve();
}

Submission (verdict: Accepted):
#include <bits/stdc++.h>
using namespace std;

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
//			सुखदुःखे समे कृत्वा लाभालाभौ जयाजयौ॥
//			ततो युद्धाय युज्यस्व नैवं पापमवाप्स्यसि॥
template <typename T, class C = std::less<T>>
using ordered_set = tree<T, null_type, C, rb_tree_tag, tree_order_statistics_node_update>;

template <typename T, class C = std::less_equal<T>>
using ordered_multiset = tree<T, null_type, C, rb_tree_tag, tree_order_statistics_node_update>;

struct custom_hash {
    static uint64_t splitmix64(uint64_t x) {
// http://xorshift.di.unimi.it/splitmix64.c
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }

    size_t operator()(uint64_t x) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(x + FIXED_RANDOM);
    }
};

#define rep(i, begin, end) for (__typeof(end) i = (begin) - ((begin) > (end)); i != (end) - ((begin) > (end)); i += 1 - 2 * ((begin) > (end)))

#define int            long long int
#define F              first
#define S              second
#define pb             push_back
#define si             std::set <int>
#define vi             std::vector <int>
#define vvi            std::vector <vector <int>>
#define pii            std::pair <int, int>
#define vpi            std::vector <pii>
#define vpp            std::vector <pair<int, pii>>
#define umii           std::unordered_map <int, int, custom_hash>
#define mii            std::map <int, int>
#define mpi            std::map <pii, int>
#define spi            std::set <pii>
#define endl "\n"
#define sz(x)          ((int) x.size())
#define all(p)         p.begin(), p.end()
#define double         long double
#define que_max        std::priority_queue <int>
#define que_min        std::priority_queue <int, vi, greater<int>>
// https://stackoverflow.com/questions/2620862/using-custom-stdset-comparator
class compare{
    bool operator()(pair<int,int> below,pair<int,int> above){
        return above < below;
    }
};
// priority_queue<pair<int,int>, vector<pair<int,int>>, compare) > pq; // custom hash for pq
#define bug(...)       __f (#__VA_ARGS__, __VA_ARGS__)
template <typename T, typename S> constexpr T ifloor(const T a, const S b) { return a / b - (a % b && (a ^ b) < 0); }
template <typename T, typename S> constexpr T iceil(const T a, const S b) { return ifloor(a + b - 1, b); }
void setIO(string name = "") {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    if (!name.empty()) {
        freopen((name + ".in").c_str(), "r", stdin);
        freopen((name + ".out").c_str(), "w", stdout);
    }
}

#define set_bits __builtin_popcountll
#define lead_zero __builtin_clzll
#define trail_zero __builtin_ctzll

int nxt() {
    int x;
    std::cin >> x;
    return x;
}

int pow(int base, int exp) {
    int res = 1;
    while (exp > 0) {
        if (exp & 1)
            res = res * base;
        base = base * base;
        exp /= 2;
    }
    return res;
}

int pow(int base, int exp, int mod) {
    int res = 1;
    while (exp > 0) {
        if (exp & 1)
            res = (res * base) % mod;
        base = (base * base) % mod;
        exp /= 2;
    }
    return res;
}

const int mod = 1000000007;
const int N = 2e5 + 5;
//////////////////////////// PNC ////////////////////////////
vi fac, inv_fac;

void precompute_factorials(int n) {
    fac.resize(n+1,1);
    inv_fac.resize(n+1,1);
    for (int i = 1; i <= n; i++) fac[i] = (fac[i-1]*i)%mod;
    inv_fac[n] = pow(fac[n], mod-2, mod);
    for (int i = n-1; i >= 0; i--) inv_fac[i] = (inv_fac[i+1]*(i+1))%mod;
}

int C(int n, int k){
    if(n>=k && k>=0){
        int ret = (fac[n] * inv_fac[k]) % mod;
        ret = (ret * inv_fac[n-k]) % mod;
        return ret;
    }else{
        return 0;
    }
}
////////////////////////////////////////////////////////////

///////////////////////////// DSU ////////////////////////////
class DisjointSets {
    private:
    vector<int> parents;
    vector<int> sizes;

    public:
    DisjointSets(int size) : parents(size), sizes(size, 1) {
        for (int i = 0; i < size; i++) parents[i] = i;
    }

    int find(int x) { return parents[x] == x ? x : (parents[x] = find(parents[x])); }

    bool unite(int x, int y) {
        int x_root = find(x);
        int y_root = find(y);
        if (x_root == y_root) { return false; }

        if (sizes[x_root] < sizes[y_root]) { swap(x_root, y_root); }
        sizes[x_root] += sizes[y_root];
        parents[y_root] = x_root;
        return true;
    }

    bool connected(int x, int y) { return find(x) == find(y); }
};
///////////////////////////////////////////////////////

///////////////////////////// SEGMENT TREE ////////////////////////////
struct Node{
    int val;
    Node(){
        val = 0;
    }

    Node(int p1){
        val = p1;
    }

    void merge(Node &l, Node &r){
        val = __gcd(l.val, r.val);
    }
};

struct SegTree {
    vector<Node> tree;
    vi arr; // type may change
    int n;
    int s;
    SegTree(int a_len, vi &a){ // change if type updated
        arr = a;
        n = a_len;
        s = 1;
        while (s < 2 * n){
            s = s << 1;
        }
        tree.resize(s);
        fill(tree.begin(), tree.end(), Node());
        build(0, n - 1, 1);
    }
    void build(int start, int end, int index){ // Never change this
        if (start == end){
            tree[index] = Node(arr[start]);
            return;
        }
        int mid = (start + end) / 2;
        build(start, mid, 2 * index);
        build(mid + 1, end, 2 * index + 1);
        tree[index].merge(tree[2 * index], tree[2 * index + 1]);
    }
    Node query(int start, int end, int index, int left, int right){ // Never change this
        if (start > right || end < left) return Node();
        if (start >= left && end <= right) return tree[index];
        int mid = (start + end) / 2;
        Node l, r, ans;
        l = query(start, mid, 2 * index, left, right);
        r = query(mid + 1, end, 2 * index + 1, left, right);
        ans.merge(l, r);
        return ans;
    }
    Node make_query(int left, int right){
        return query(0, n - 1, 1, left, right);
    }
};
///////////////////////////////////////////////////////

void solve(){
    int n = nxt();
    vector<si> g(n);
    vi d(n);

    rep(i,0,n-1){
        int u = nxt()-1, v = nxt()-1;
        g[u].insert(v);
        g[v].insert(u);
        d[u]++;
        d[v]++;
    }

    vector<si> v(n);
    rep(i,0,n) v[d[i]].insert(i);

    int x = n-1;
    while(x >= 0 && v[x].empty()) x--;

    int res = 0;
    rep(i,0,n){
        v[d[i]].erase(i);
        for(auto j: g[i]){
            v[d[j]].erase(j);
            v[d[j]-1].insert(j);
        }
        int y = x;
        while(y >= 0 && v[y].empty()) y--;
        res = max(res, d[i]+y-1);

        v[d[i]].insert(i);
        for(auto j: g[i]){
            v[d[j]].insert(j);
            v[d[j]-1].erase(j);
        }
    }
    cout << res << endl;
}

int32_t main() {
    setIO();
    //std::cout<<std::fixed<<std::setprecision(0);
    //set_factorial(N+1);
    int t=1;
    std::cin>>t;
    while(t--) solve();
}