#include <bits/stdc++.h>
#define int long long
using namespace std;
struct Edge{int go; int c; int f;};
vector<int> where, d, vert;
vector<Edge> edges;
vector<bool> used;
vector<vector<int> > data;
int number, m;
queue<int> q;
int INF = 1e15;
void construct_edge(int u, int v, int c){
    Edge e1 = {v, c, 0};
	Edge e2 = {u, 0, 0};
    edges.push_back(e1);
	edges.push_back(e2);
	data[u].push_back(edges.size() - 2);
	data[v].push_back(edges.size() - 1);
}
int dfs(int vertex, int flow, int maximum){
    if (vertex == number - 1) return flow;
    while (where[vertex] < data[vertex].size()){
        int i = where[vertex];
		int edge_number = data[vertex][i];
        int to = edges[edge_number].go;
        int can = min(edges[edge_number].c - edges[edge_number].f, flow);
        if (can < maximum || d[to] != d[vertex] + 1) {
            where[vertex]++;
            continue;
        }
        int fl = dfs(to, can, maximum);
        if (fl >= maximum){
            edges[edge_number].f += fl;
            edges[edge_number^1].f -= fl;
            return fl;
        }
        where[vertex]++;
    }
    return 0;
}
void bfs(int maximum){
    while (!q.empty()){
        int vertex = q.front();
        q.pop();
        for (int i=0; i < data[vertex].size(); i++){
			int edge_number = data[vertex][i];
            int nv = edges[edge_number].go;
            int can = edges[edge_number].c - edges[edge_number].f;
            if (d[nv] == -1 && can >= maximum){
                d[nv] = d[vertex] + 1;
                q.push(nv);
            }
        }
    }
}
void DFS(int vertex){
    used[vertex] = true;
    vert.push_back(vertex);
    for (int i=0; i < data[vertex].size(); i++){
        int e = data[vertex][i];
        if (edges[e].f == edges[e].c) continue;
        if (used[edges[e].go]) continue;
        DFS(edges[e].go);
    }
}
int dinic(){
    int A = 1LL << 60;
    while (A > 0){
        while (true){
            for (int i=0; i < number; i++){
                where[i] = 0;
                d[i] = -1;
            }
            d[0] = 0;
            q.push(0);
            bfs(A);
            if (d[number-1] == -1) break;
            while (true){
                int flow = dfs(0, INF, A);
                if (flow < A) break;
            }
        }
        A /= 2;
    }
    int ans = 0;
    for (int i=0; i < data[0].size(); i++){
        ans += edges[data[0][i]].f;
    }
    return ans;
}
signed main()
{
    int n;
    cin >> n;
    number = 2*n+1;
    for (int i=0; i < number; i++){
        where.push_back(0);
        used.push_back(false);
        d.push_back(0);
        vector<int> help;
        data.push_back(help);
    }
    for (int i=0; i < n-1; i++) construct_edge(0, i+1, 1);
    for (int i=0; i < n; i++) construct_edge(n+i, number-1, 1);
    vector<vector<int> > where(n), tot(n-1);
    for (int i=0; i < n-1; i++){
        int x;
        cin >> x;
        for (int j=0; j < x; j++){
            int a;
            cin >> a;
            tot[i].push_back(a-1);
            where[a-1].push_back(i);
            construct_edge(i+1, n+a-1, 1);
        }
    }
    int res = dinic();
    if (res != n-1){
        cout << -1;
        return 0;
    }
    vector<int> nei;
    for (int i=1; i < n; i++){
        for (int j=0; j < data[i].size(); j++){
            if (data[i][j] % 2 != 0) continue;
            int num = data[i][j];
            if (edges[num].f > 0){
                nei.push_back(edges[num].go - n);
            }
        }
    }
    //for (int i=0; i < n-1; i++) cout << nei[i] << endl;
    set<int> kek;
    for (int i=0;i<n-1; i++) kek.insert(nei[i]);
    for (int i=0; i < n; i++) if (!kek.count(i)) nei.push_back(i);
    set<int> may;
    set<int> used, e;
    e.insert(nei.back());
    for (int i=0; i < where[nei.back()].size(); i++){
        may.insert(where[nei.back()][i]);
    }
    vector<pair<int, int> > ans(n-1);
    for (int i=0; i < n-1; i++){
        if (!may.size()){
            cout <<-1;
            return 0;
        }
        auto it = may.begin();
        int num = *it;
        may.erase(it);
        int element = nei[num];
        for (int j=0; j < tot[num].size(); j++){
            int N = tot[num][j];
            if (e.count(N)){
                ans[num] = {N, element};
                break;
            }
        }
        used.insert(num);
        e.insert(element);
        for (int j=0; j < where[element].size(); j++){
            int T = where[element][j];
            if (!used.count(T)) may.insert(T);
        }
    }
    for (int i=0;i<n-1;i++) cout << ans[i].first+1 << " " << ans[i].second+1 << endl;
    return 0;
}


Measured memory_bytes: 67852