#include <bits/stdc++.h>
using namespace std;
template <class T>
bool mini(T &a, T b) {
  return a > b ? (a = b, true) : false;
}
template <class T>
bool maxi(T &a, T b) {
  return a < b ? (a = b, true) : false;
}
signed main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout.precision(10);
  cout << fixed;
  int n;
  cin >> n;
  map<pair<int, int>, set<pair<int, int>>> THIRD;
  map<int, set<pair<int, int>>> SEC;
  set<pair<int, int>> ONE;
  vector<vector<int>> a(n, vector<int>(3));
  for (int i = 0; i < (int)(n); i++) {
    cin >> a[i][0] >> a[i][1] >> a[i][2];
    ONE.insert({a[i][0], i});
    SEC[a[i][0]].insert({a[i][1], i});
    THIRD[{a[i][0], a[i][1]}].insert({a[i][2], i});
  }
  while (ONE.size()) {
    auto u = *ONE.begin();
    int id = u.second;
    ONE.erase({a[id][0], id});
    SEC[a[id][0]].erase({a[id][1], id});
    THIRD[{a[id][0], a[id][1]}].erase({a[id][2], id});
    int X = ONE.begin()->first;
    auto it = SEC[X].lower_bound({a[id][1], -1});
    if (it == SEC[X].end()) it--;
    int Y = a[it->second][1];
    it = THIRD[{X, Y}].lower_bound({a[id][2], -1});
    if (it == THIRD[{X, Y}].end()) it--;
    int des = it->second;
    ONE.erase({a[des][0], des});
    SEC[X].erase({a[des][1], des});
    THIRD[{X, Y}].erase({a[des][2], des});
    cout << id + 1 << ' ' << des + 1 << "\n";
  }
}
