#include <bits/stdc++.h>
using namespace std;
long long mod = 1000000007LL;
long long base = 10000007;
long long large = 1000000000000000000LL;
int read(string &s, int &pos) {
  int x = 0;
  while (s[pos] >= '0' && s[pos] <= '9') {
    x *= 10;
    x += (int)(s[pos] - '0');
    pos++;
  }
  return x;
}
class UnionFind {
 private:
  vector<int> p, rank;

 public:
  UnionFind(int n) {
    rank.assign(n, 0);
    p.assign(n, 0);
    for (int i = 0; i < n; i++) {
      p[i] = i;
    }
  }
  int findSet(int i) { return (p[i] == i) ? i : (p[i] = findSet(p[i])); }
  bool isSameSet(int i, int j) { return findSet(i) == findSet(j); }
  void unionSet(int i, int j) {
    if (!isSameSet(i, j)) {
      int x = findSet(i), y = findSet(j);
      p[x] = y;
    }
  }
};
int n;
vector<vector<int> > adj;
vector<vector<int> > bel, cnt;
vector<int> fa;
void dfs(int u, int pa, int ga) {
  fa[u] = ga;
  for (int j = 0; j < (int)adj[u].size(); j++) {
    int v = adj[u][j];
    if (v != pa) {
      dfs(v, u, ga);
    }
  }
}
void f(int x, bool &can) {
  fa.assign(n, -1);
  for (int j = 0; j < (int)adj[x].size(); j++) {
    int v = adj[x][j];
    dfs(v, x, v);
  }
  for (int j = 0; j < n; j++) {
    if (j == x) continue;
    if (bel[x][j] != bel[x][fa[j]]) can = false;
  }
}
int main() {
  cin >> n;
  bool can = true;
  bel.assign(n, vector<int>(n, -1));
  cnt = bel;
  for (int i = 0; i < n; i++) {
    string s;
    cin >> s;
    int temp = 0;
    int pos = 0;
    int x = 0;
    char ul = '-';
    while (ul == '-') {
      int k = read(s, pos);
      ul = s[pos++];
      cnt[i][temp] = k;
      while (k--) {
        x = read(s, pos);
        x--;
        bel[i][x] = temp;
        if (pos < (int)s.length())
          ul = s[pos++];
        else
          ul = '!';
      }
      temp++;
    }
  }
  for (int i = 0; i < n; i++) {
    if (bel[i][i] != -1) can = false;
  }
  vector<pair<int, int> > e;
  for (int i = 0; i < n; i++) {
    for (int j = i + 1; j < n; j++) {
      if (cnt[i][bel[i][j]] + cnt[j][bel[j][i]] == n) {
        e.push_back(pair<int, int>(i, j));
      }
    }
  }
  if ((int)e.size() != n - 1)
    can = false;
  else {
    UnionFind uf(n + 10);
    for (int i = 0; i < (int)e.size(); i++) {
      int x = e[i].first;
      int y = e[i].second;
      if (!uf.isSameSet(x, y)) {
        uf.unionSet(x, y);
      } else {
        can = false;
      }
    }
  }
  if (can) {
    adj.assign(n, vector<int>(0, 0));
    for (int i = 0; i < n - 1; i++) {
      int x, y;
      x = e[i].first;
      y = e[i].second;
      adj[x].push_back(y);
      adj[y].push_back(x);
    }
    for (int i = 0; i < n; i++) f(i, can);
  }
  if (can) {
    cout << n - 1 << endl;
    for (int i = 0; i < n - 1; i++) {
      cout << e[i].first + 1 << " " << e[i].second + 1 << endl;
    }
  } else {
    cout << -1 << endl;
  }
  return 0;
}
