#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7, N = 1e5 + 5;
const long long inf = 1e18;
namespace uchiha {
template <class T>
using v = vector<T>;
template <class T>
using vv = vector<vector<T>>;
template <class T, class U>
using p = pair<T, U>;
template <class T, class U>
using m = map<T, U>;
template <class T>
using pri = priority_queue<T>;
template <class T>
using rpi = priority_queue<T, v<T>, greater<T>>;
using vc = v<char>;
using vs = v<string>;
using vd = v<long double>;
using vvi = vector<vector<long long>>;
using vvb = vector<vector<bool>>;
template <class T>
void rd(T& a) {
  cin >> a;
}
template <class T>
void rd(v<T>& a) {
  for (long long i = 0; i < (long long)(long long)a.size(); i++) cin >> a[i];
}
template <class T>
void rd(vv<T>& a) {
  for (long long i = 0; i < (long long)(long long)a.size(); i++) rd(a[i]);
}
template <class T, class U>
void rd(pair<T, U>& p) {
  cin >> p.first >> p.second;
}
template <class T, class... Args>
void rd(T& a, Args&... args) {
  cin >> a;
  rd(args...);
}
template <class T>
void print(T a) {
  cout << a << endl;
}
template <class T>
void print(v<T> a) {
  for (auto x : a) {
    cout << x << ' ';
  }
  cout << endl;
}
template <class T>
void print(vv<T> a) {
  for (auto x : a) {
    print(x);
  }
}
template <class T, class U>
void print(pair<T, U> p) {
  cout << p.first << ' ' << p.second << endl;
}
template <class T>
void print(set<T> s) {
  for (auto it = s.begin(); it != s.end(); it++) {
    cout << (*it) << ' ';
  }
  cout << endl;
}
template <class T, class... Args>
void print(T& a, Args&... args) {
  cout << a << ' ';
  print(args...);
}
long long mintwo(long long x) { return __builtin_ctzll(x); }
long long maxtwo(long long x) { return (long long)log2(x); }
long long onebits(long long x) { return __builtin_popcountll(x); }
long long ceil(long long a, long long b) { return (a + b - 1) / b; }
void yes() { cout << "YES" << endl; }
void no() { cout << "NO" << endl; }
void subl() {}
template <class T>
long long size(v<T> a) {
  return (long long)a.size();
}
template <class T>
long long size(set<T> s) {
  return (long long)s.size();
}
template <class T, class U>
long double pdiv(T a, U b) {
  return (1.0 * a) / (1.0 * b);
}
template <class T, class U>
void chmin(T& a, U b) {
  if (a > b) a = b;
}
template <class T, class U>
void chmax(T& a, U b) {
  if (a < b) a = b;
}
template <class T, class U>
T min(T a, U b) {
  if (a > b) a = b;
  return a;
}
template <class T, class U>
T max(T a, U b) {
  if (a < b) a = b;
  return a;
}
template <class T>
T min(v<T> a) {
  return *min_element((a).begin(), (a).end());
}
template <class T>
T max(v<T> a) {
  return *max_element((a).begin(), (a).end());
}
template <class T>
T sum(v<T> a) {
  T su = 0;
  for (auto x : a) su = (su + x);
  return su;
}
template <class T, class U>
T POW(T x, U y) {
  T a = 1;
  while (y) {
    if (y & 1) a = (a * x) % mod;
    x = (x * 1ll * x) % mod;
    y >>= 1;
  }
  return a;
}
template <class T>
v<T> pre_sum(v<T> a) {
  for (long long i = 1;
       (1 - size(a) < 0) ? i < (long long)size(a) : i > (long long)size(a);
       (1 - size(a) < 0) ? i++ : i--)
    a[i] = (a[i] + a[i - 1]);
  return a;
}
template <class T>
v<T> suf_sum(v<T> a) {
  for (long long i = size(a) - 2;
       (size(a) - 2 - -1 < 0) ? i < (long long)-1 : i > (long long)-1;
       (size(a) - 2 - -1 < 0) ? i++ : i--)
    a[i] = (a[i] + a[i + 1]);
  return a;
}
vector<long long> Finv, Ninv;
void factfill(vector<long long>& fact, long long n) {
  fact.assign(n + 1, 1);
  Ninv = fact;
  Finv = fact;
  for (long long i = 2; i <= n; i++) fact[i] = (fact[i - 1] * i) % mod;
  for (long long i = 2; i <= n; i++)
    Ninv[i] = Ninv[mod % i] * (mod - mod / i) % mod;
  for (long long i = 2; i <= n; i++) Finv[i] = (Ninv[i] * Finv[i - 1]) % mod;
}
void sieve(vector<long long>& primes, long long n) {
  primes.resize(n + 1, 0ll);
  primes[1] = 1;
  long long p = 2;
  for (; p * p <= n; p++) {
    if (!primes[p]) {
      primes[p] = p;
      for (long long q = p * p; q < n + 1; q += p) primes[q] = p;
    }
  }
  for (; p <= n; p++)
    if (!primes[p]) primes[p] = p;
}
long double _c = clock();
inline bool tle() {
  bool b = (((clock() - _c) / CLOCKS_PER_SEC) > 3);
  if (b) cerr << "TLE";
  return b;
}
}  // namespace uchiha
using namespace uchiha;
void mangekyo();
vv<long long> adj;
v<long long> dist, parent;
v<bool> vis;
void dfs(long long u = 1, long long par = 0) {
  vis[u] = 1;
  for (auto v : adj[u]) {
    if (vis[v] || v == par) continue;
    dist[v] = dist[u] + 1;
    parent[v] = u;
    dfs(v, u);
  }
}
void solve() {
  long long n;
  rd(n);
  adj.assign(n + 1, vector<long long>());
  vv<long long> inp;
  for (long long i = 0; i < (long long)n - 1; i++) {
    long long x, y;
    rd(x, y);
    adj[x].push_back(y);
    adj[y].push_back(x);
    inp.push_back({x, y});
  }
  dist.assign(n + 1, 0);
  vis.assign(n + 1, 0);
  parent.assign(n + 1, 0);
  dfs();
  long long start = max_element((dist).begin(), (dist).end()) - dist.begin();
  dist.assign(n + 1, 0);
  vis.assign(n + 1, 0);
  parent.assign(n + 1, 0);
  dfs(start);
  long long finish = max_element((dist).begin(), (dist).end()) - dist.begin();
  vector<long long> path;
  for (long long cur = finish; cur != 0; cur = parent[cur]) {
    path.push_back(cur);
  }
  pri<long long> pq;
  for (long long i = 0; i < (long long)n - 1; i++) pq.push(i);
  map<pair<long long, long long>, long long> mp;
  for (auto v : inp) {
    mp[{v[0], v[1]}] = -1;
  }
  for (long long i = 1; i < (long long)path.size(); i++) {
    mp[{path[i - 1], path[i]}] = pq.top();
    mp[{path[i], path[i - 1]}] = pq.top();
    pq.pop();
  }
  for (auto v : inp) {
    long long cur = mp[{v[0], v[1]}];
    if (cur == -1) {
      cout << pq.top() << '\n';
      pq.pop();
    } else
      cout << cur << '\n';
  }
}
int32_t main() {
  mangekyo();
  solve();
  cerr << "Time: " << fixed << setprecision(5)
       << ((clock() - _c) / CLOCKS_PER_SEC);
  ;
}
void mangekyo() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  ;
  srand(time(NULL));
  subl();
}
