#include <bits/stdc++.h>
using namespace std;
void Find_size(int v);
void Build(int root, vector<int> &values);
void Solve();
long long RAND(long long n) { return abs((rand() << 15) + rand()) % n; }
int n;
vector<vector<int>> g;
vector<vector<int>> edges;
vector<bool> used;
vector<int> Size;
vector<int> val;
int Find_centroid(int v, int sz) {
  used[v] = true;
  Find_size(v);
  int max_size = -1;
  for (auto to : g[v]) {
    if (!used[to] && Size[to] > sz / 2 &&
        (max_size == -1 || Size[to] > Size[max_size])) {
      max_size = to;
    }
  }
  int ans;
  if (max_size == -1) {
    ans = v;
  } else {
    ans = Find_centroid(max_size, sz);
  }
  used[v] = false;
  return ans;
}
void Find_size(int v) {
  Size[v] = 1;
  used[v] = true;
  for (auto to : g[v]) {
    if (!used[to]) {
      Find_size(to);
      Size[v] += Size[to];
    }
  }
  used[v] = false;
}
void Build(int root, vector<int> &values) {
  int cur_ind = 0;
  used[root] = true;
  queue<int> q;
  q.push(root);
  while (!q.empty()) {
    int cur = q.front();
    q.pop();
    for (auto to : g[cur]) {
      if (!used[to]) {
        used[to] = true;
        q.push(to);
        edges[cur][to] = values[cur_ind++] - val[cur];
        edges[to][cur] = edges[cur][to];
        val[to] = val[cur] + edges[cur][to];
      }
    }
  }
}
vector<int> parent;
vector<int> cap;
void make_set(int x) {
  parent[x] = x;
  cap[x] = Size[x];
}
int find_set(int x) {
  if (x == parent[x]) return x;
  return parent[x] = parent[find_set(parent[x])];
}
void union_sets(int x, int y) {
  int a = find_set(x);
  int b = find_set(y);
  if (a != b) {
    if (cap[a] < cap[b]) swap(a, b);
    parent[b] = a;
    cap[a] += cap[b];
  }
}
void Solve() {
  int c = Find_centroid(0, n);
  Find_size(c);
  auto compare = [](int lhs, int rhs) { return cap[lhs] > cap[rhs]; };
  std::priority_queue<int, std::vector<int>, decltype(compare)> q(compare);
  for (auto i : g[c]) {
    make_set(i);
    q.push(i);
  }
  while (q.size() > 2) {
    int x = q.top();
    q.pop();
    int y = q.top();
    q.pop();
    union_sets(x, y);
    q.push(find_set(x));
  }
  int x = q.top();
  q.pop();
  int y = q.top();
  q.pop();
  vector<int> gr1(cap[find_set(x)]);
  vector<int> gr2(cap[find_set(y)]);
  for (int i = 0; i < (int)gr1.size(); ++i) {
    gr1[i] = i + 1;
  }
  for (int i = 0; i < (int)gr2.size(); ++i) {
    gr2[i] = (i + 1) * (gr1.size() + 1);
  }
  for (auto i : g[c]) {
    if (find_set(i) == y) {
      used[i] = true;
    }
  }
  Build(c, gr1);
  for (auto i : g[c]) {
    if (find_set(i) == y) {
      used[i] = false;
    }
  }
  Build(c, gr2);
  for (int i = 0; i < n; ++i) {
    used[i] = false;
  }
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
  cout.tie(nullptr);
  cin >> n;
  if (n == 1) {
    return 0;
  }
  g.resize(n);
  used.resize(n);
  edges.resize(n, vector<int>(n, -1));
  Size.resize(n);
  parent.resize(n);
  cap.resize(n);
  val.resize(n);
  for (int i = 0; i < n - 1; ++i) {
    int u, v;
    cin >> u >> v;
    u--, v--;
    g[u].push_back(v);
    g[v].push_back(u);
  }
  Solve();
  for (int i = 0; i < n; ++i) {
    for (int j = i + 1; j < n; ++j) {
      if (edges[i][j] >= 0) {
        cout << i + 1 << ' ' << j + 1 << ' ' << edges[i][j] << endl;
      }
    }
  }
  return 0;
}
