#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>

#pragma GCC optimize("-O3")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")

#define in insert
#define all(x) x.begin(), x.end()
#define sz(x) (int) x.size()
#define sqr(x) ((x) * (x))
#define pb push_back
#define fi first
#define se second
#define fr(i, l, r) for (int i = l; i <= r; ++i)
#define rf(i, r, l) for (int i = r; i >= l; --i)
#define fast_io ios_base::sync_with_stdio(0); cin.tie(0);
#define stop system("pause");
#define x1 fdffgahj
#define y1 fdffgga

using namespace __gnu_pbds;
using namespace std;

template <typename T>
using sset = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

typedef unsigned long long ull;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int N = 1e6 + 10;
const int MXN = 30;
const int M = 1e3 + 10;
const int inf = 1e9 + 1;
const ll INF = 1e18 + 1e2;
const int mod = 1e9 + 7;

template <typename T>
void vout(T x){
    cout << x << endl;
    exit(0);
}

int n;
vector<pii> g[N];

int main() {
    fast_io

    cin >> n;
    fr(i, 1, n - 1) {
        int x, y;
        cin >> x >> y;
        g[x].pb({y, i});
        g[y].pb({x, i});
    }

    vector<int> ans(n, -1);

    if (n > 2) {
        int cnt = 0;
        fr(i, 1, n) {
            if (sz(g[i]) >= 3) {
                for (auto j : g[i])
                    ans[j.se] = cnt++;

                break;
            }
        }

        fr(i, 1, n - 1)
            if (ans[i] == -1)
                ans[i] = cnt++;

        fr(i, 1, n - 1)
            cout << ans[i] << "\n";
    } else {
        int ans = 0;
        fr(i, 1, n) cout << ans++ << endl;
    }

    return 0;
}
