#include <bits/stdc++.h>
using namespace std;
template <class T>
using max_pq = priority_queue<T>;
template <class T>
using min_pq = priority_queue<T, vector<T>, greater<T>>;
long long int x, y;
template <class T>
T gcd(T a, T b) {
  if (a == 0) {
    x = 0, y = 1;
    return b;
  }
  T gc = gcd(b % a, a);
  T temp;
  temp = x;
  x = y - (b / a) * temp;
  y = temp;
  return gc;
}
long long int po(long long int a, long long int x) {
  if (x == 0) {
    return 1;
  }
  long long int ans = 1;
  long long int k = 1;
  while (k <= x) {
    if (x & k) {
      ans = ((ans * a));
    }
    k <<= 1;
    a *= a;
  }
  return ans;
}
string second[1001];
vector<int> leaf;
vector<int> edges[200005];
pair<long long int, int> en[200005];
set<long long int> tree[1005];
int cedge[200005];
int g = 0;
int n;
long long int val[1000005];
long long int val1[1000005];
void convert(int m) {
  int va = 0;
  int i = 0;
  while (second[m][i] != ':') {
    va = va * 10 + (second[m][i] - 48);
    i++;
  }
  if (va == n - 1) {
    leaf.push_back(m);
  }
  {
    i = -1;
    long long int t1, t2;
    do {
      va = 0;
      i++;
      while (second[m][i] != ':') {
        va = va * 10 + (second[m][i] - 48);
        i++;
      }
      cedge[m]++;
      t1 = 0;
      t2 = 0;
      for (int j = 0; j < va; j++) {
        i++;
        long long int va1 = 0;
        while (second[m][i] != ',' && second[m][i] != '-' &&
               i < second[m].size()) {
          va1 = va1 * 10 + (second[m][i] - 48);
          i++;
        }
        t1 += val[va1];
        t2 += val1[va1];
        t1 %= 1432344041;
        t2 %= 1000000009;
      }
      t1 |= (t2 << 31);
      en[g++] = make_pair(t1, m);
      tree[m].insert(t1);
    } while (second[m][i] == '-');
  }
}
long long int te1[200005], te2[200005];
map<pair<int, int>, int> mark;
int main() {
  ios::sync_with_stdio(false);
  cout.tie(0);
  cin.tie(0);
  int t;
  val[0] = 1;
  val1[0] = 1;
  for (int i = 1; i < 1000005; i++) {
    val[i] = val[i - 1] * 999347;
    val1[i] = val1[i - 1] * 107729;
    val1[i] %= 1000000009;
    val[i] %= 1432344041;
  }
  t = 1;
  while (t--) {
    cin >> n;
    int i;
    for (i = 1; i <= n; i++) {
      cin >> second[i];
      convert(i);
    }
    sort(en, en + g);
    long long int t1 = 0, t2 = 0;
    for (i = 0; i < leaf.size(); i++) {
      t1 = 0;
      t2 = 0;
      t1 += val[leaf[i]];
      t2 += val1[leaf[i]];
      t1 %= 1432344041;
      t2 %= 1000000009;
      t1 |= (t2 << 31);
      int k = lower_bound(en, en + g, make_pair(t1, 10005)) - en;
      k = en[k - 1].second;
      te1[k] += val[leaf[i]];
      te2[k] += val1[leaf[i]];
      te1[k] %= 1432344041;
      te2[k] %= 1000000009;
      edges[leaf[i]].push_back(k);
      edges[k].push_back(leaf[i]);
    }
    int cn = leaf.size();
    while (cn < n) {
      for (int x = 1; x <= n; x++) {
        if (edges[x].size() == cedge[x] - 1) {
          te1[x] += val[x];
          te2[x] += val1[x];
          te1[x] %= 1432344041;
          te2[x] %= 1000000009;
          t1 = te1[x] | (te2[x] << 31);
          int k = lower_bound(en, en + g, make_pair(t1, 10005)) - en;
          k = en[k - 1].second;
          te1[k] += te1[x];
          te2[k] += te2[x];
          te1[k] %= 1432344041;
          te2[k] %= 1000000009;
          edges[x].push_back(k);
          edges[k].push_back(x);
          break;
        }
      }
      cn++;
    }
    vector<pair<int, int>> ans;
    for (i = 1; i <= n; i++) {
      for (auto u : edges[i]) {
        if (edges[i].size() != cedge[i] && n != 2) {
          cout << -1;
          return 0;
        }
        if (mark[{u, i}] != 1) {
          mark[{u, i}] = 1;
          mark[{i, u}] = 1;
          ans.push_back(make_pair(u, i));
        }
      }
    }
    if (ans.size() == n - 1) {
      cout << n - 1 << '\n';
      for (auto u : ans) {
        cout << u.first << " " << u.second << '\n';
      }
    } else {
      cout << -1 << '\n';
    }
  }
}
