#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<pii> vii;
typedef vector<pll> vll;
#define ordered_set tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update>
#define ordered_multiset tree<int, null_type, less_equal<int>, rb_tree_tag, tree_order_statistics_node_update>
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define ff first
#define ss second
#define mp make_pair

const int N = 2e5 + 1;
int podd[N], odw[N];
vi graf[N], zb;

int wyn = 0;

void dfs_podd(int v, int ojc){
    podd[v] = 1;
    for(int u : graf[v]){
        if(odw[u] || u == ojc) continue;
        dfs_podd(u, v);
        podd[v] += podd[u];
    }
}

int znajdz(int v, int ojc, int r){
    for(int u : graf[v]){
        if(odw[u] || u == ojc) continue;
        if(podd[u] > r / 2) return znajdz(u, v, r);
    }
    return v;
}

int zbierz(int v, int ojc, ll odl){
    int nodl = odl + graf[v].size() - 2;
    int w = nodl;
    for(int u : graf[v]){
        if(u == ojc || odw[u]) continue;
        w = max(w, zbierz(u, v, nodl));
    }
    return w;
}


void decompose(int v){
    dfs_podd(v, 0);
    int r = podd[v];
    int c = znajdz(v, 0, r);
    int best = 0;
    for(int u : graf[c]){
        int akt = zbierz(u, c, 0);
        wyn = max(wyn, akt + best + int(graf[c].size()));
        best = max(akt, best);
    }

    odw[c] = 1;
    for(int u : graf[c]){
        if(odw[u]) continue;
        decompose(u);
    }

}

int main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    int n; cin >> n;
    for(int i = 1; i < n; i++){
        int a, b; cin >> a >> b;
        graf[a].pb(b); graf[b].pb(a);
    }

    decompose(1);


    cout << wyn << "\n";



    return 0;
}