#include <bits/stdc++.h>
using namespace std;
template <typename T>
void UMAX(T &a, T b) {
  a = (a > b ? a : b);
}
template <typename T>
void UMIN(T &a, T b) {
  a = (a < b ? a : b);
}
long long readint() {
  char c = getchar();
  long long ret = 0ll;
  bool neg = 0;
  while (!(c >= '0' && c <= '9')) {
    if (c == '-') neg = 1;
    c = getchar();
  }
  while (c >= '0' && c <= '9') {
    ret = ret * 10ll + (long long)(c - '0');
    c = getchar();
  }
  return neg ? -ret : ret;
}
void putint(long long v) {
  if (v < 0) {
    putchar('-');
    v = -v;
  }
  if (!v) {
    putchar('0');
    return;
  }
  if (v >= 10ll) putint(v / 10ll);
  putchar('0' + (v % 10ll));
}
pair<int, int> operator+(pair<int, int> A, pair<int, int> B) {
  return make_pair(A.first + B.first, A.second + B.second);
}
pair<int, int> operator-(pair<int, int> A, pair<int, int> B) {
  return make_pair(A.first - B.first, A.second - B.second);
}
bool ccw(pair<int, int> C, pair<int, int> A, pair<int, int> B) {
  A = A - C;
  B = B - C;
  return (long long)A.first * B.second > (long long)A.second * B.first;
}
namespace convexhull {
vector<pair<int, int> > graham(vector<pair<int, int> > ps) {
  int i, t, s = 0;
  sort(ps.begin(), ps.end());
  vector<pair<int, int> > ret;
  for (i = 0; i < (int)ps.size(); ++i) {
    while (s >= 2 && !ccw(ret[s - 2], ps[i], ret[s - 1])) --s, ret.pop_back();
    ++s, ret.push_back(ps[i]);
  }
  t = s;
  for (i = (int)ps.size() - 2; i >= 0; --i) {
    while (s > t && !ccw(ret[s - 2], ps[i], ret[s - 1])) --s, ret.pop_back();
    ++s, ret.push_back(ps[i]);
  }
  ret.pop_back();
  return ret;
}
}  // namespace convexhull
map<pair<int, int>, int> mtp, mid;
vector<pair<pair<int, int>, pair<int, int> > > res;
int n, tp[1005];
pair<int, int> ps[1005];
bool intri(pair<int, int> P, pair<int, int> A, pair<int, int> B,
           pair<int, int> C) {
  if (P == A || P == B || P == C) return 1;
  return ccw(A, B, P) != ccw(A, C, P) && ccw(B, A, P) != ccw(B, C, P) &&
         ccw(C, A, P) != ccw(C, B, P);
}
void solve(vector<pair<int, int> >, bool);
void trans(const vector<pair<int, int> > &vec, pair<int, int> A,
           pair<int, int> B, pair<int, int> C) {
  vector<pair<int, int> > go;
  for (pair<int, int> P : vec) {
    if (intri(P, A, B, C)) go.push_back(P);
  }
  solve(go, 0);
}
void solve(vector<pair<int, int> > ps, bool ini = 0) {
  if ((int)ps.size() <= 1) return;
  vector<pair<int, int> > conv = convexhull::graham(ps);
  vector<int> tp;
  int i, j, k, eqc = 0;
  for (pair<int, int> P : conv) tp.push_back(mtp[P]);
  for (i = 0; i < (int)tp.size(); ++i)
    eqc += (tp[i] == tp[(i + 1) % tp.size()]);
  if (eqc < (int)tp.size() - 2) {
    printf("Impossible\n");
    exit(0);
  }
  if (eqc == (int)tp.size()) {
    pair<int, int> cen = make_pair(19260817, 0);
    for (pair<int, int> P : ps) {
      if (mtp[P] != mtp[conv[0]]) {
        cen = P;
        break;
      }
    }
    if (cen.first == 19260817) {
      set<pair<int, int> > st(conv.begin(), conv.end());
      for (i = 1; i < (int)ps.size(); ++i) {
        if (ini || conv.size() != 3 || st.find(ps[i]) == st.end())
          res.push_back(make_pair(ps[0], ps[i]));
      }
    } else {
      for (i = 0; i < (int)conv.size(); ++i) {
        if ((ini || conv.size() != 3) && i < (int)conv.size() - 1)
          res.push_back(make_pair(conv[i], conv[i + 1]));
        trans(ps, conv[i], conv[(i + 1) % conv.size()], cen);
      }
    }
  } else if (conv.size() == 2) {
    if (tp[0] == tp[1]) res.push_back(make_pair(conv[0], conv[1]));
  } else if (conv.size() > 3 || ini) {
    for (i = 0; i < (int)tp.size(); ++i) {
      if (tp[i] == tp[(i + 1) % (int)tp.size()])
        res.push_back(make_pair(conv[i], conv[(i + 1) % (int)tp.size()]));
    }
    pair<int, int> cen[2] = {make_pair(19260817, 0), make_pair(19260817, 0)};
    for (i = 0; i < (int)conv.size(); ++i) {
      if (tp[i] != tp[(i + 1) % tp.size()]) cen[tp[i]] = conv[i];
    }
    for (i = 0; i < (int)conv.size(); ++i) {
      if (tp[i] == tp[(i + 1) % tp.size()])
        trans(ps, conv[i], conv[(i + 1) % conv.size()], cen[!tp[i]]);
    }
  } else if (conv.size() == 3) {
    int mino = (tp[0] + tp[1] + tp[2] == 2 ? 0 : 1), minoid;
    for (i = 0; i < 3; ++i) {
      if (tp[i] == mino) minoid = i;
    }
    for (pair<int, int> P : ps) {
      if (P == conv[0] || P == conv[1] || P == conv[2]) continue;
      if (mtp[P] == mino) {
        res.push_back(make_pair(P, conv[minoid]));
        trans(ps, P, conv[0], conv[1]);
        trans(ps, P, conv[1], conv[2]);
        trans(ps, P, conv[2], conv[0]);
        return;
      }
    }
    for (pair<int, int> P : ps) {
      if (P == conv[0] || P == conv[1] || P == conv[2]) continue;
      res.push_back(make_pair(P, conv[(minoid + 1) % 3]));
    }
  }
}
int main() {
  int i, j, k;
  n = readint();
  for (i = 0; i < n; ++i) {
    int x = readint(), y = readint(), c = readint();
    ps[i] = make_pair(x, y);
    tp[i] = c;
    mtp[ps[i]] = tp[i];
    mid[ps[i]] = i;
  }
  solve(vector<pair<int, int> >(ps, ps + n), 1);
  vector<pair<int, int> > nres;
  for (auto P : res) {
    int x = mid[P.first], y = mid[P.second];
    nres.push_back(make_pair(min(x, y), max(x, y)));
  }
  sort(nres.begin(), nres.end());
  nres.erase(unique(nres.begin(), nres.end()), nres.end());
  printf("%d\n", (int)nres.size());
  for (auto P : nres) {
    printf("%d %d\n", P.first, P.second);
  }
  return 0;
}
