#include <bits/stdc++.h>
using namespace std;
long long rdtsc() {
  long long tmp;
  asm("rdtsc" : "=A"(tmp));
  return tmp;
}
int rnd() { return ((rand() << 15) ^ rand()); }
int rnd(int x) { return rnd() % x; }
const int INF = (int)1.01e9;
const long double EPS = 1e-9;
const int maxn = (int)1e3 + 10;
const int maxk = (maxn + 31) / 32;
unsigned int sets[maxn][maxk];
int n, k;
int read() {
  if (scanf("%d", &n) < 1) {
    return 0;
  }
  k = (n + 31) / 32;
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < k; ++j) {
      sets[i][j] = 0;
    }
    int cnt;
    scanf("%d", &cnt);
    for (int j = 0; j < cnt; ++j) {
      int x;
      scanf("%d", &x);
      --x;
      sets[i][x / 32] |= (1u << (x & 31));
    }
  }
  return 1;
}
int d[maxn][maxn];
int vs[maxn][maxn][2];
int edge[maxn][maxn];
unsigned int madmask[maxk];
unsigned int toand[maxk];
unsigned int wholemask[maxk];
int leaf[maxn];
int cnts[2];
int lasts[2][maxn];
int cur[maxn];
void solve() {
  if (n == 2) {
    printf("1 2\n");
    return;
  }
  for (int a = 0; a < n; ++a) {
    for (int b = 0; b < n; ++b) {
      int &res = d[a][b];
      res = 0;
      for (int i = 0; i < k && res <= 2; ++i) {
        unsigned int cur = (sets[a][i] & sets[b][i]);
        if (cur) {
          unsigned int val = cur;
          for (int it = 0; it < 32; ++it, val >>= 1) {
            if (val & 1u) {
              if (res == 2) {
                res = 3;
                break;
              }
              vs[a][b][res++] = i * 32 + it;
            }
          }
        }
      }
    }
  }
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      edge[i][j] = 0;
    }
  }
  bool three = 0;
  for (int a = 0; a < n; ++a) {
    for (int b = 0; b < n; ++b) {
      if (d[a][b] != 2) {
        continue;
      }
      three = 1;
      int s = vs[a][b][0], t = vs[a][b][1];
      edge[s][t] = edge[t][s] = 1;
    }
  }
  if (!three) {
    for (int i = 1; i < n; ++i) {
      printf("1 %d\n", i + 1);
    }
    return;
  }
  int notleafcnt = 0;
  for (int i = 0; i < n; ++i) {
    leaf[i] = 1;
    for (int j = 0; j < n; ++j) {
      if (edge[i][j]) {
        leaf[i] = 0;
        ++notleafcnt;
        break;
      }
    }
  }
  assert(notleafcnt >= 2);
  if (notleafcnt == 2) {
    int cntm = 0;
    for (int a = 0; a < n; ++a) {
      int cnt = 0;
      for (int i = 0; i < n; ++i) {
        if (sets[a][i / 32] & (1u << (i & 31))) {
          continue;
        }
        cur[cnt++] = i;
      }
      if (cnt) {
        bool fail = 0;
        for (int j = 0; j < cntm; ++j) {
          if (cnts[j] != cnt) {
            continue;
          }
          bool ok = 0;
          for (int p = 0; p < cnt; ++p) {
            if (cur[p] != lasts[j][p]) {
              ok = 1;
              break;
            }
          }
          if (!ok) {
            fail = 1;
            break;
          }
        }
        if (fail) {
          continue;
        }
        assert(cntm < 2);
        cnts[cntm] = cnt;
        for (int i = 0; i < cnt; ++i) {
          lasts[cntm][i] = cur[i];
        }
        ++cntm;
      }
    }
    int vs[2];
    int tmp = 0;
    for (int i = 0; i < n; ++i) {
      if (!leaf[i]) {
        assert(tmp < 2);
        vs[tmp++] = i;
      }
    }
    assert(tmp == 2);
    printf("%d %d\n", vs[0] + 1, vs[1] + 1);
    for (int it = 0; it < cntm; ++it) {
      for (int i = 0; i < cnts[it]; ++i) {
        int v = lasts[it][i];
        printf("%d %d\n", vs[it] + 1, v + 1);
      }
    }
    return;
  } else {
    for (int p = 0; p < k; ++p) {
      toand[p] = 0;
    }
    for (int i = 0; i < n; ++i) {
      if (leaf[i]) {
        continue;
      }
      toand[i / 32] ^= (1u << (31 & i));
    }
    for (int v = 0; v < n; ++v) {
      if (leaf[v]) {
        continue;
      }
      for (int p = 0; p < k; ++p) {
        madmask[p] = 0;
      }
      madmask[v / 32] |= (1u << (v & 31));
      for (int u = 0; u < n; ++u) {
        if (leaf[u] || !edge[v][u]) {
          continue;
        }
        madmask[u / 32] |= (1u << (u & 31));
      }
      bool first = 1;
      for (int a = 0; a < n; ++a) {
        if (!((sets[a][v / 32] >> (v & 31)) & 1)) {
          continue;
        }
        for (int b = 0; b < n; ++b) {
          if (d[a][b] < 3) {
            continue;
          }
          bool ok = 1;
          for (int i = 0; i < k; ++i) {
            unsigned int cur = (sets[a][i] & sets[b][i]);
            if ((cur & toand[i]) != madmask[i]) {
              ok = 0;
              break;
            }
          }
          if (!ok) {
            continue;
          }
          for (int i = 0; i < k; ++i) {
            unsigned int cur = (sets[a][i] & sets[b][i]);
            cur ^= madmask[i];
            if (first) {
              wholemask[i] = cur;
            } else {
              wholemask[i] &= cur;
            }
          }
          first = 0;
        }
      }
      assert(!first);
      for (int i = 0; i < k; ++i) {
        wholemask[i] ^= madmask[i];
        if (wholemask[i]) {
          unsigned int val = wholemask[i];
          for (int it = 0; it < 32; ++it, val >>= 1) {
            if (val & 1u) {
              int s = v, t = i * 32 + it;
              edge[s][t] = edge[t][s] = 1;
            }
          }
        }
      }
    }
  }
  for (int i = 0; i < n; ++i) {
    for (int j = i + 1; j < n; ++j) {
      if (edge[i][j]) {
        printf("%d %d\n", i + 1, j + 1);
      }
    }
  }
}
int main() {
  srand(rdtsc());
  while (1) {
    if (!read()) {
      break;
    }
    solve();
  }
  return 0;
}
