#include <bits/stdc++.h>
using namespace std;
inline void proc_status() {
  ifstream t("/proc/self/status");
  cerr << string(istreambuf_iterator<char>(t), istreambuf_iterator<char>())
       << endl;
}
namespace fastIO {
const unsigned int BUFFER_SIZE = (unsigned int)1 << 15;
char buffer[BUFFER_SIZE], *cur, *ed;
inline char getc() {
  return *(cur == ed    ? ed = buffer + fread(buffer, 1, BUFFER_SIZE, stdin),
           cur = buffer : cur)++;
}
}  // namespace fastIO
using fastIO::getc;
template <typename T>
inline T read() {
  register T sum(0), fg(1);
  register char ch(getc());
  for (; !isdigit(ch); ch = getc())
    if (ch == '-') fg = -1;
  for (; isdigit(ch); ch = getc()) sum = sum * 10 - '0' + ch;
  return sum * fg;
}
template <typename T>
inline T sqr(const T &val) {
  return val * val;
}
template <typename T>
inline int chkmin(T &a, const T &b) {
  return b < a ? a = b, 1 : 0;
}
template <typename T>
inline int chkmax(T &a, const T &b) {
  return b > a ? a = b, 1 : 0;
}
const int MAXN = (int)1e3;
int n;
bitset<MAXN + 5> id[MAXN + 5];
inline void input() {
  n = read<int>();
  for (int i = 1; i <= n; ++i)
    for (int k = read<int>(); k--;) id[read<int>()].set(i);
}
inline void solve() {
  static int d[MAXN + 5][MAXN + 5];
  for (int i = 1; i <= n; ++i)
    for (int j = i + 1; j <= n; ++j)
      d[j][i] = d[i][j] = (id[i] & id[j]).count();
  static bitset<MAXN + 5> S3[MAXN + 5], S4[MAXN + 5];
  int cnt3 = 0, cnt4 = 0;
  for (int i = 1; i <= n; ++i)
    for (int j = i + 1; j <= n; ++j) {
      if (d[i][j] == 1) S4[i].set(j), S4[j].set(i), ++cnt4;
      if (d[i][j] == 2) S3[i].set(j), S3[j].set(i), ++cnt3;
    }
  if (n == 2) {
    puts("1 2");
    return;
  } else if (cnt3 == 0) {
    for (int i = 2; i <= n; ++i) printf("%d %d\n", 1, i);
    return;
  } else if (cnt4 == 0) {
    static vector<int> V[2], mid;
    int left = 0;
    for (int i = 1; i <= n; ++i)
      if (S3[i].any()) {
        left = i;
        break;
      }
    V[0].push_back(left);
    for (int i = 1; i <= n; ++i)
      if (i != left) {
        if (S3[i].none())
          mid.push_back(i);
        else
          V[S3[left].test(i)].push_back(i);
      }
    for (auto i : V[0]) printf("%d %d\n", i, mid[0]);
    printf("%d %d\n", mid[0], mid[1]);
    for (auto i : V[1]) printf("%d %d\n", i, mid[1]);
    return;
  }
  static vector<pair<int, int> > E;
  int core = 0;
  for (int i = 1; i <= n; ++i)
    if (S3[i].none() && S4[i].none()) {
      core = i;
      break;
    }
  if (core != 0) {
    for (int i = 1; i <= n; ++i)
      if (i != core && S4[i].none()) E.emplace_back(core, i);
    for (int i = 1; i <= n; ++i)
      if (S4[i].any()) {
        int fa = 0;
        for (int j = 1; j <= n; ++j)
          if (j != i && j != core && S4[j].none() && !S3[i].test(j)) {
            fa = j;
            break;
          }
        E.emplace_back(fa, i);
      }
  } else {
    static vector<int> mid;
    for (int i = 1; i <= n; ++i)
      if (S4[i].none()) mid.push_back(i);
    if (((int)(mid).size()) >= 2) E.emplace_back(mid[0], mid[1]);
    for (int i = 1; i <= n; ++i)
      for (int j = i + 1; j <= n; ++j)
        if (d[i][j] > 2)
          if ((S3[i] & S4[j]).count() + (S4[i] & S3[j]).count() > 0)
            E.emplace_back(i, j);
  }
  for (auto it : E) printf("%d %d\n", it.first, it.second);
}
int main() {
  input();
  solve();
  return 0;
}
