#include <bits/stdc++.h>
#pragma GCC optimize(2)
#pragma GCC optimize(3)
using namespace std;
template <typename T1, typename T2>
void ckmin(T1 &a, T2 b) {
  if (a > b) a = b;
}
template <typename T1, typename T2>
void ckmax(T1 &a, T2 b) {
  if (a < b) a = b;
}
template <typename T>
T gcd(T a, T b) {
  return b ? gcd(b, a % b) : a;
}
int read() {
  int x = 0, f = 0;
  char ch = getchar();
  while (!isdigit(ch)) f |= ch == '-', ch = getchar();
  while (isdigit(ch)) x = 10 * x + ch - '0', ch = getchar();
  return f ? -x : x;
}
const int N = 1002;
vector<pair<int, int> > ans;
bitset<N> bit[N], e[N], leaf, used;
int n;
int main() {
  n = read();
  int ju = 1;
  for (int i = 0; i < n; i++) {
    int l = read();
    ju &= l == n;
    while (l--) {
      int x = read() - 1;
      bit[i].set(x);
    }
  }
  if (ju) {
    for (int i = 1; i < n; i++) {
      printf("%d %d\n", 1, i + 1);
    }
    return 0;
  }
  for (int i = 0; i < n; i++) leaf.set(i);
  for (int i = 0; i < n; i++) {
    for (int j = i + 1; j < n; j++) {
      bitset<N> tmp = bit[i] & bit[j];
      if (tmp.count() == 2) {
        int u, v;
        for (u = 0; u < n; u++)
          if (tmp[u]) break;
        for (v = n - 1; v >= 0; v--)
          if (tmp[v]) break;
        if (e[u][v]) continue;
        ans.push_back({u, v});
        leaf[u] = leaf[v] = 0;
        e[u].set(v), e[v].set(u);
      }
    }
  }
  if (ans.size() == 1) {
    int u = ans[0].first, v = ans[0].second;
    for (int i = 0; i < n; i++)
      if (bit[i].count() != n) {
        for (int j = 0; j < n; j++)
          if (j != u && j != v) {
            if (bit[i][j])
              ans.push_back({j, u});
            else
              ans.push_back({j, v});
          }
        break;
      }
  } else {
    for (int i = 0; i < n; i++)
      if (leaf[i] && !used[i]) {
        bitset<N> tt;
        for (int j = 0; j < n; j++) tt.set(j);
        for (int j = 0; j < n; j++) {
          if (bit[j][i]) tt = tt & bit[j];
        }
        bitset<N> lf = tt & leaf, to = tt ^ lf;
        int j, ok = 0;
        for (j = 0; j < n; j++)
          if (to[j]) {
            to.flip(j);
            if (to == e[j]) ok = 1;
            to.flip(j);
            if (ok) break;
          }
        for (int u = 0; u < n; u++)
          if (lf[u]) {
            ans.push_back({u, j});
            used[u] = 1;
          }
      }
  }
  for (auto v : ans) {
    printf("%d %d\n", v.first + 1, v.second + 1);
  }
  return 0;
}
