//#define  NDEBUG

//#pragma optimize("tree-vectorize")
//#pragma optimize ("fast-math")
//#pragma optimize ("O3")

#include <bits/stdc++.h>

using namespace std;

#define all(v)                  v.begin(), v.end()
#define db(x)                   cout << #x << " = " << (x) << "\n"
#define fend(x)                 ((x) & ((x)+1)) - 1
#define fenu(x)                 (x) | ((x)+1)
#define forn(i, n)              for (int i = 0; i < (int)n; ++i)
#define forr(i, b, e)           for (int i = b; i < (int)e; ++i)
#define ft                      first
#define len(s)                  s.length()
#define mp                      std::make_pair
#define pob                     pop_back
#define pof                     pop_front
#define pub                     push_back
#define puf                     push_front
#define sc                      second

typedef double dbl;
typedef long double ldbl;
typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;

const long long MILLER_RABIN = 3215031751;
const long double PI = acos(-1);

#if __cplusplus >= 201103L

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

struct config_io {
    config_io() {
        cin.tie(nullptr);
        cout.tie(nullptr);
        ios_base::sync_with_stdio(false);
    }
} cnf_io;

struct config_rand {
    config_rand() {
        srand(chrono::duration_cast<chrono::nanoseconds>(
                chrono::high_resolution_clock::now().time_since_epoch()).count());
    }
} cnf_rand;

namespace std {
    template<>
    struct hash<pair<int, int> > {
        size_t operator()(const pair<int, int> &x) const {
            return (x.first * 71ll + x.second) % ((int) 1e9 + 7);
        }
    };

    template<>
    struct hash<vector<int>> {
        size_t operator()(const vector<int> &v) const {
            size_t hsh = 0;
            for (int i = 0; i < v.size(); ++i) {
                hsh = (hsh * 71ll + v[i]) % (int) (1e9 + 7);
            }
            return hsh;
        }
    };
}

template<class T>
using ordered_set = __gnu_pbds::tree<T, __gnu_pbds::null_type, less<T>, __gnu_pbds::rb_tree_tag, __gnu_pbds::tree_order_statistics_node_update>;
//ordered_set<int>  s;
//s.insert(3);
//cout << s.order_of_key(2) << endl; // the number of elements in the s less than 2
//cout << *s.find_by_order(0) << endl; // print the 0-th smallest number in s(0-based)

// __builtin_popcount(x) - Returns the number of 1-bits in x.
// __builtin_parity(x) - Returns the parity of x, i.e. the number of 1-bits in x modulo 2.
// __builtin_ffs(x) - Returns one plus the index of the least significant 1-bit of x, or if x is zero, returns zero.
// __builtin_clz(x) - Returns the number of leading 0-bits in x, starting at the most significant bit position. If x is 0, the result is undefined.
// __builtin_ctz(x) - Returns the number of trailing 0-bits in x, starting at the least significant bit position. If x is 0, the result is undefined.

//inline string tobin(long long x) { bitset<63>(x).to_string(); }

template<class T>
void trace(T collection) {
    for (auto elem : collection) { cout << elem << " "; }
    cout << endl;
}

#endif

const int ML = 1e5 + 10;
vector<int> g[ML];
int f[ML];

int most_sign_bit(int x) {
    return 31 - __builtin_clz(x);
}

int first_zero_bit(int x) {
    int i = 0;
    while (x & (1 << i)) ++i;
    return i;
}

void dfs(int v, int par = -1) {
    f[v] = 0;
    forn(i, g[v].size()) {
        int to = g[v][i];
        if (to == par) continue;
        dfs(to, v);
    }
    int d = 1 << 20;
    while (d) {
        int cnt = 0;
        forn(i, g[v].size()) {
            int to = g[v][i];
            if (to == par) continue;
            if (f[to] & d) cnt++;
        }
        if (cnt > 1) {
            f[v] += d << 1;
            return;
        }
        if (cnt == 1) f[v] |= d;
        d >>= 1;
    }
    f[v] += 1;
}

void solve(int test) {
    int n;
    cin >> n;
    forn(i, n - 1) {
        int u, v;
        cin >> u >> v;
        --u, --v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    dfs(0);
    //cout << bitset<32>(f[0]) << endl;
    cout << most_sign_bit(f[0]) << endl;
}

int main() {
#ifdef HOME
    freopen("home.in", "r", stdin);
    freopen("home.out", "w", stdout);
#endif

    int tests = 1;
    //cin >> tests;
    for (int test = 1; test <= tests; ++test) {
        solve(test);
    }

#ifdef HOME
    cout << "\n\nTime: " << clock() / (double) CLOCKS_PER_SEC << endl;
#endif
    return 0;
}

Measured memory_bytes: 11776