#include <bits/stdc++.h>
template <typename T>
using arr = std::vector<T>;
struct pair {
  int a, b;
  bool operator<(const pair &p) const { return a != p.a ? a < p.a : b < p.b; }
  bool operator==(const pair &p) const { return a == p.a && b == p.b; }
};
template <typename T>
struct mtx {
  size_t s1, s2;
  arr<T> A;
  void assign(int _s1, int _s2, T v) { A.assign((s1 = _s1) * (s2 = _s2), v); }
  T &operator()(int i1, int i2) { return A[i1 * s2 + i2]; }
};
struct Sol {
  int n;
  arr<int> S, B0;
  mtx<int> B2, B1;
  arr<pair> out, exp;
  bool b2_eq(int i, int j) {
    for (int k = 0; k < (n); ++k)
      if (B2(i, k) != B2(j, k)) return 0;
    return 1;
  }
  int b2_inter(int i, int j) {
    int c = 0;
    for (int k = 0; k < (n); ++k) c += B2(i, k) & B2(j, k);
    return c;
  }
  void b1_set(int i, int j, int k) {
    for (int l = 0; l < (n); ++l) B1(i, l) = B2(j, l) & B2(k, l);
  }
  template <typename Rnd>
  void gen(int _n, Rnd &rnd) {
    while (1) {
      n = _n;
      exp.clear();
      out.clear();
      arr<int> A(n);
      for (int i = 0; i < (n); ++i) A[i] = i;
      std::shuffle(A.begin(), A.end(), rnd);
      mtx<int> T;
      T.assign(n, n, 0);
      for (int i = 0; i < (n); ++i)
        if (i) {
          int j = rnd() % i;
          T(i, j) = T(j, i) = 1;
          exp.push_back(pair{i, j});
        }
      S.assign(n, 0);
      B2.assign(n, n, 0);
      B1.assign(n, n, 0);
      B0.assign(n, -1);
      for (int i = 0; i < (n); ++i)
        for (int j = 0; j < (n); ++j)
          if (T(i, j)) B2(A[i], j) = B2(A[j], i) = 1;
      for (int i = 0; i < (n); ++i)
        for (int j = 0; j < (n); ++j)
          for (int k = 0; k < (n); ++k)
            if (T(i, j) && T(j, k)) B2(A[i], k) = B2(A[k], i) = 1;
      for (int i = 0; i < (n); ++i)
        for (int j = 0; j < (n); ++j) S[i] += B2(i, j);
      if (all().size() < 2) break;
    }
  }
  void debug_b2() {
    for (int i = 0; i < (n); ++i) {
      printf("%d | ", S[i]);
      for (int j = 0; j < (n); ++j) printf("%d ", B2(i, j));
      puts("");
    }
  }
  void read() {
    scanf("%d", &n);
    S.resize(n);
    B2.assign(n, n, 0);
    B1.assign(n, n, 0);
    B0.assign(n, -1);
    for (int i = 0; i < (n); ++i) {
      scanf("%d", &S[i]);
      for (int j = 0; j < (S[i]); ++j) {
        int a;
        scanf("%d", &a);
        B2(i, --a) = 1;
      }
    }
  }
  arr<int> all() {
    arr<int> r;
    for (int i = 0; i < (n); ++i) {
      bool ok = 1;
      for (int j = 0; j < (n); ++j) ok &= B2(j, i);
      if (ok) r.push_back(i);
    }
    return r;
  }
  void dfs(int v, int p) {
    int x = 0;
    while (x == v || x == B0[p] || !B1(p, x)) x++;
    int y = 0;
    while (y < n && (B2(y, x) || !B2(y, B0[p]) || !B2(y, v))) y++;
    if (y == n) return;
    int w = 0;
    while (!B2(p, w) || !B2(y, w) || B1(p, w)) w++;
    int r = 0;
    while (r == p || !B2(r, x) || !B2(r, w)) r++;
    B0[r] = v;
    b1_set(r, p, y);
    push(r, p);
    for (int i = 0; i < (n); ++i)
      if (B1(r, i) && i != B0[p] && i != v) dfs(i, r);
  }
  void push(int r, int p) {
    for (int i = 0; i < (n); ++i)
      if (B1(r, i) && i != B0[r] && i != B0[p]) out.push_back(pair{B0[r], i});
  }
  void print_out() {
    for (pair p : out) printf("%d %d\n", p.a + 1, p.b + 1);
  }
  void norm(arr<pair> &A) {
    for (pair &p : A)
      if (p.a > p.b) std::swap(p.a, p.b);
    std::sort(A.begin(), A.end());
  }
  void debug(int r) {
    printf("%d : ", B0[r]);
    for (int i = 0; i < (n); ++i)
      if (i != B0[r] && B1(r, i)) printf("%d ", i);
    printf(": ");
    for (int i = 0; i < (n); ++i)
      if (!B1(r, i) && B2(r, i)) printf("%d ", i);
    printf("\n");
  }
  void run() {
    arr<int> a = all();
    if (a.size() == n) {
      for (int i = 0; i < (n - 1); ++i) out.push_back(pair{i, n - 1});
      return;
    }
    if (a.size() == 2) {
      int x = 0;
      while (S[x] == n) x++;
      for (int j = 0; j < (n); ++j)
        if (j != a[1]) out.push_back(pair{j, a[B2(x, j)]});
      return;
    }
    int x = 0;
    for (int i = 0; i < (n); ++i)
      if (S[i] > S[x]) x = i;
    arr<int> C(n);
    for (int i = 0; i < (n); ++i) C[i] = b2_inter(i, x);
    arr<int> b0(n, 1);
    for (int i = 0; i < (n); ++i)
      for (int j = 0; j < (n); ++j) b0[j] &= (C[i] < 3) ^ B2(i, j);
    for (int i = 0; i < (n); ++i)
      if (b0[i]) B0[x] = i;
    int y = -1;
    for (int i = 0; i < (n); ++i)
      if (C[i] < C[x] && (y == -1 || C[i] > C[y])) y = i;
    int z = -1;
    for (int i = 0; i < (n); ++i)
      if (C[i] < C[x] && (z == -1 || C[i] > C[z]) && C[i] > b2_inter(i, y))
        z = i;
    b1_set(x, y, z);
    push(x, x);
    for (int i = 0; i < (n); ++i)
      if (i != B0[x] && B1(x, i)) dfs(i, x);
  }
};
void test(int n) {
  std::mt19937 rnd(762834);
  ;
  while (1) {
    Sol S;
    S.gen(n, rnd);
    S.run();
    S.norm(S.out);
    S.norm(S.exp);
    if (S.out == S.exp) {
      puts("OK");
      continue;
    }
    puts("ERROR");
    printf("exp = ");
    for (pair p : S.exp) printf("(%d,%d) ", p.a, p.b);
    puts("");
    printf("out = ");
    for (pair p : S.out) printf("(%d,%d) ", p.a, p.b);
    puts("");
    exit(1);
  }
}
int main() {
  Sol S;
  S.read();
  S.run();
  S.print_out();
  return 0;
}
