/* GCC */

#include <stdio.h>
#include <vector>
#include <queue>

using namespace std;

int n; // Кількість вершин графа
vector<queue<int> > all; // all[v - 1] — список суміжності вершини v
queue<pair<int, int> > edges; // Черга з ребер, які виводимо у вихідний файл

// Видаляє передній елемент зі списку суміжності вершини v та оновлює чергу ребер, які
// ми виводимо у вихідний файл, додавши туди нове доступне ребро, якщо таке з’явилося.
inline void pop(int v)
{
    all[v - 1].pop();
    if (!all[v - 1].empty())
    {
        int adjacent = all[v - 1].front();
        if (!all[adjacent - 1].empty() && all[adjacent - 1].front() == v)
            edges.push(make_pair(min(v, adjacent), max(v, adjacent)));
    }
}

int main()
{
    freopen("graph.in", "r", stdin);
    freopen("graph.out", "w", stdout);

    scanf("%d\n", &n);

    // Зчитуємо інформацію та заносимо початкові ребра в чергу edges:
    for (int v = 1; v <= n; v++)
    {
        queue<int> adj; // Список вершин, суміжних з поточною
        int num = 0; // Поточне зчитуване число
        while (true)
        {
            char c;
            scanf("%c", &c); // Оскільки кількість чисел у рядку невідома, зчитуємо посимвольно
            if (c >= '0' && c <= '9') // Якщо черговий зчитаний символ — цифра
                num = num * 10 + (c - '0');
            else // Якщо черговий зчитаний символ — пробіл або перенесення рядка
            {
                adj.push(num);
                num = 0;
            }
            if (c == '\n') // Якщо ми дійшли до кінця рядка, виходимо з циклу
                break;
        }
        all.push_back(adj);
        // Якщо передня вершина списку суміжності уже опрацьована, і в її списку суміжності
        // поточна розглядувана вершина теж є передньою, додаємо це ребро до черги:
        if (adj.front() < v && all[adj.front() - 1].front() == v)
            edges.push(make_pair(adj.front(), v));
    }

    while (!edges.empty())
    {
        pair<int, int> edge = edges.front();
        edges.pop();
        printf("%d %d\n", edge.first, edge.second);
        pop(edge.first);
        pop(edge.second);
    }

    return 0;
}
