#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;

#define FILL(a, n, x) memset((a), (x), sizeof ((a)[0]) * (n))
#define FILLA(a, x) memset((a), (x), sizeof (a))
#define COPY(a, n, b) memcpy((b), (a), sizeof ((a)[0]) * (n))
#define COPYA(a, b) memcpy((b), (a), sizeof (a))

typedef unsigned long long lu;
typedef long long li;
typedef pair<int, int> pii;
const int mod = 1e9 + 7;

inline int Add(int x) { return x >= mod ? x - mod : x; }
inline void Add(int &x, int y) { x += y; if (x >= mod) x -= mod; }
inline int Sub(int x) { return x < 0 ? x + mod : x; }
inline void Sub(int &x, int y) { x = Sub(x - y); }
inline int Mul(int x, int y) { return (int)((lu)x * y % mod); }
inline int Mul(int x, int y, int z) { return (int)((lu)x * y % mod * z % mod); }

int Pow(int x, int y) {
  int z = 1;
  for (; y; y >>= 1) {
    if (y & 1) z = Mul(z, x);
    x = Mul(x, x);
  }
  return z;
}

int Inv(int x) { return Pow(x, mod - 2); }
template <class T> inline void Max(T &x, T y) { if (y > x) x = y; }
template <class T> inline void Min(T &x, T y) { if (y < x) x = y; }

// ----------------------------------------

namespace dinic {
  const int maxn = 1e6, maxm = 1e6;
  typedef int FlowType;
  const FlowType inf_f = ~0U >> 1;

  void Init(int n);
  void AddEdge(int u, int v, FlowType cap, li id);
  FlowType Solve(int s, int t);
  vector< pair<li, FlowType> > Result(void);
}

namespace dinic {
  struct Edge {
    int v;
    li id;
    FlowType cap, cap0;
  } edge[maxm << 1];

  int n, m, s, t;
  vector<int> g[maxn];

  void Init(int _n) {
    n = _n, m = 0;
    for (int i = 0; i < n; ++i) g[i].clear();
  }

  void AddEdge(int u, int v, FlowType c, li id = -1) {
    g[u].push_back(m);
    edge[m++] = (Edge){v, id, c, c};
    g[v].push_back(m);
    edge[m++] = (Edge){u, id, 0, 0};
  }

  int iter[maxn], dist[maxn];

  bool Bfs(void) {
    queue<int> que;
    que.push(s);
    FILL(dist, n, -1);
    dist[s] = 0;
    while (!que.empty()) {
      int u = que.front(); que.pop();
      for (int i = 0; i < g[u].size(); ++i) {
        Edge &e = edge[g[u][i]];
        if (e.cap && dist[e.v] == -1) {
          dist[e.v] = dist[u] + 1;
          que.push(e.v);
        }
      }
    }
    return dist[t] >= 0;
  }

  FlowType Dfs(int u, FlowType f) {
    if (u == t) return f;
    FlowType sum = 0;
    for (int &i = iter[u]; i < g[u].size(); ++i) {
      Edge &e = edge[g[u][i]], &rev = edge[g[u][i] ^ 1];
      if (e.cap && dist[e.v] == dist[u] + 1) {
        FlowType res = Dfs(e.v, min(f - sum, e.cap));
        e.cap -= res;
        rev.cap += res;
        if ((sum += res) == f) break;
      }
    }
    return sum;
  }

  FlowType Solve(int _s, int _t) {
    s = _s, t = _t;
    FlowType ans = 0;
    while (Bfs()) {
      FILL(iter, n, 0);
      ans += Dfs(s, inf_f);
    }
    return ans;
  }

  vector< pair<li, FlowType> > Result(void) {
    vector< pair<li, FlowType> > ans;
    for (int u = 0; u < n; ++u) {
      for (int i = 0; i < g[u].size(); ++i) {
        Edge &e = edge[g[u][i]];
        if (e.cap < e.cap0 && e.id != -1) {
          ans.push_back(make_pair(e.id, e.cap0 - e.cap));
        }
      }
    }
    return ans;
  }
}

// ----------------------------------------

const int maxn = 1e5;
int n;
vector<int> E[maxn];
vector<int> F[maxn];

int match[maxn], par[maxn];
int A[maxn], B[maxn];

void NoSolution(void) {
  puts("-1");
  exit(0);
}

int main(void) {
  scanf("%d", &n);
  for (int i = 0; i < n - 1; ++i) {
    int c;
    scanf("%d", &c);
    while (c--) {
      int x;
      scanf("%d", &x);
      --x;
      E[i].push_back(x);
      F[x].push_back(i);
    }
  }

  // root = 0
  int L = 0, R = n, S = R + n - 1, T = S + 1, N = T + 1;
  dinic::Init(N);
  for (int i = 1; i < n; ++i) {
    dinic::AddEdge(S, L + i, 1, -1);
  }
  for (int i = 0; i < n - 1; ++i) {
    dinic::AddEdge(R + i, T, 1, -1);
  }
  for (int i = 1; i < n; ++i) {
    for (int j : F[i]) {
      dinic::AddEdge(L + i, R + j, 1, (li)i * n + j);
    }
  }
  int flow = dinic::Solve(S, T);
  if (flow < n - 1) NoSolution();

  vector< pair<li, int> > way = dinic::Result();
  for (pair<li, int> p : way) {
    int x = (int)(p.first / n), y = (int)(p.first % n);
    match[y] = x;
  }

  queue<int> que;
  que.push(0);
  FILL(par, n, -1);
  while (!que.empty()) {
    int u = que.front(); que.pop();
    for (int j : F[u]) {
      int i = match[j];
      if (par[i] == -1) {
        par[i] = u;
        A[j] = i;
        B[j] = u;
        que.push(i);
      }
    }
  }
  for (int i = 1; i < n; ++i) {
    if (par[i] == -1) NoSolution();
  }
  for (int i = 0; i < n - 1; ++i) {
    printf("%d %d\n", A[i] + 1, B[i] + 1);
  }
  return 0;
}


Measured memory_bytes: 74720