#include <bits/stdc++.h>
using pii = std::pair<int, int>;
const int N = 2010;
template <typename T = int>
inline T read() {
  T x = 0, f = 0;
  char ch = getchar();
  while (!isdigit(ch)) f |= ch == '-', ch = getchar();
  while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
  return f ? -x : x;
}
struct Point {
  int x, y;
  inline Point(int _x = 0, int _y = 0) { x = _x, y = _y; }
  inline friend int operator*(const Point &a, const Point &b) {
    return a.x * b.y - b.x * a.y;
  }
  inline friend Point operator-(const Point &a, const Point &b) {
    return Point(a.x - b.x, a.y - b.y);
  }
  inline double ang() { return atan2(y, x); }
};
inline int dis(Point A, Point B) {
  return (A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y);
}
inline int left(Point A, Point B, Point C) {
  int tmp = (B - A) * (C - A);
  return tmp < 0 || tmp == 0 && dis(A, B) >= dis(A, C);
}
struct Node {
  Point p;
  int idx, col;
  inline friend int operator!=(Node &A, Node &B) {
    return A.p.x != B.p.x || A.p.y != B.p.y;
  }
} a[N], stk[N];
std::vector<pii> res;
int f[N];
inline int find(int u) { return f[u] == u ? f[u] : f[u] = find(f[u]); }
inline void Merge(int u, int v) {
  if (find(u) == find(v)) return;
  res.emplace_back(u, v), f[find(u)] = f[find(v)];
}
inline int area(Point A, Point B, Point C) { return abs((B - A) * (C - A)); }
inline int Inside(Point A, Point B, Point C, Point pt) {
  return area(A, B, C) == area(A, B, pt) + area(A, C, pt) + area(B, C, pt);
}
inline std::vector<Node> divide(Node A, Node B, Node C, std::vector<Node> S) {
  std::vector<Node> vec;
  for (auto pt : S)
    if (pt != A && pt != B && pt != C && Inside(A.p, B.p, C.p, pt.p))
      vec.push_back(pt);
  return vec;
}
inline void solve(Node A, Node B, Node C, std::vector<Node> vec) {
  int flg = true;
  Node p;
  if (A.col == B.col && A.col != C.col) std::swap(A, C);
  if (A.col == C.col && A.col != B.col) std::swap(A, B);
  if (find(B.idx) != find(C.idx)) Merge(B.idx, C.idx);
  for (auto pt : vec)
    if (pt.col == A.col) flg = false, p = pt;
  if (flg) {
    for (auto pt : vec)
      if (find(B.idx) != find(pt.idx)) Merge(B.idx, pt.idx);
    return;
  }
  solve(A, B, p, divide(A, B, p, vec));
  solve(A, C, p, divide(A, C, p, vec));
  solve(B, C, p, divide(B, C, p, vec));
}
int main() {
  int n = read(), p = 0, cnt = 0;
  for (int i = 0; i < n; ++i) {
    a[i].p.x = read(), a[i].p.y = read(), a[i].col = read(),
    a[i].idx = f[i] = i;
    if (a[i].p.y < a[p].p.y || a[i].p.y == a[p].p.y && a[i].p.x < a[p].p.x)
      p = i;
  }
  std::swap(a[0], a[p]);
  for (int i = 1; i < n; ++i) a[i].p = a[i].p - a[0].p;
  a[0].p = Point(0, 0);
  std::sort(a + 1, a + n,
            [&](Node A, Node B) { return A.p.ang() < B.p.ang(); });
  int t = 2;
  stk[1] = a[0], stk[2] = a[1], a[n] = a[0];
  for (int i = 2; i < n; ++i) {
    while (t > 1 && !left(stk[t - 1].p, a[i].p, stk[t].p)) --t;
    stk[++t] = a[i];
  }
  stk[0] = stk[t], stk[t + 1] = stk[1];
  for (int i = 1; i <= t; ++i) cnt += stk[i].col != stk[i - 1].col;
  std::vector<Node> All(n);
  for (int i = 0; i < n; ++i) All[i] = a[i];
  switch (cnt) {
    case 0: {
      int flg = true, col = stk[0].col, p = -1;
      for (int i = 1; i < n; ++i)
        if (a[i].col != col) flg = false, p = i;
      if (flg) {
        printf("%d\n", n - 1);
        for (int i = 1; i < n; ++i) printf("0 %d\n", i);
        return 0;
      }
      for (int i = 1; i <= t; ++i)
        solve(stk[i], stk[i - 1], a[p], divide(stk[i], stk[i - 1], a[p], All));
      break;
    }
    case 2: {
      int l = 0, r = 0;
      std::vector<Node> vec1, vec2;
      for (int i = 1; i <= t; ++i)
        if (stk[i].col != stk[i - 1].col) {
          l = i;
          break;
        }
      for (int i = l; i <= t; ++i)
        if (stk[i].col != stk[i + 1].col) {
          r = i + 1;
          break;
        }
      for (int i = r; i <= t; ++i) vec1.push_back(stk[i]);
      for (int i = 1; i <= l - 1; ++i) vec1.push_back(stk[i]);
      for (int i = l; i <= r - 1; ++i) vec2.push_back(stk[i]);
      for (int i = 0; i + 1 < vec1.size(); ++i)
        solve(vec1[i], vec1[i + 1], vec2[0],
              divide(vec1[i], vec1[i + 1], vec2[0], All));
      for (int i = 0; i + 1 < vec2.size(); ++i)
        solve(vec2[i], vec2[i + 1], vec1[0],
              divide(vec2[i], vec2[i + 1], vec1[0], All));
      break;
    }
    default:
      return puts("Impossible"), 0;
  }
  printf("%d\n", res.size());
  for (auto dat : res) printf("%d %d\n", dat.first, dat.second);
  return 0;
}
