Problem:
Score : 2200 points

Problem Statement

You are given N-1 subsets of \{1,2,...,N\}. Let the i-th set be E_i.

Let us choose two distinct elements u_i and v_i from each set E_i, and consider a graph T with N vertices and N-1 edges, whose vertex set is \{1,2,..,N\} and whose edge set is (u_1,v_1),(u_2,v_2),...,(u_{N-1},v_{N-1}).
Determine if T can be a tree by properly deciding u_i and v_i.
If it can, additionally find one instance of (u_1,v_1),(u_2,v_2),...,(u_{N-1},v_{N-1}) such that T is actually a tree.

Constraints

2 \leq N \leq 10^5

E_i is a subset of \{1,2,..,N\}.

|E_i| \geq 2

The sum of |E_i| is at most 2 \times 10^5.

Input

Input is given from Standard Input in the following format:

N
c_1 w_{1,1} w_{1,2} ... w_{1,c_1}
:
c_{N-1} w_{N-1,1} w_{N-1,2} ... w_{N-1,c_{N-1}}

Here, c_i stands for the number of elements in E_i, and w_{i,1},...,w_{i,c_i} are the c_i elements in c_i.
Here, 2 \leq c_i \leq N, 1 \leq w_{i,j} \leq N, and w_{i,j} \neq w_{i,k} (1 \leq j < k \leq c_i) hold.

Output

If T cannot be a tree, print -1; otherwise, print the choices of (u_i,v_i) that satisfy the condition, in the following format:

u_1 v_1
:
u_{N-1} v_{N-1}

Sample Input 1

5
2 1 2
3 1 2 3
3 3 4 5
2 4 5

Sample Output 1

1 2
1 3
3 4
4 5

Sample Input 2

6
3 1 2 3
3 2 3 4
3 1 3 4
3 1 2 4
3 4 5 6

Sample Output 2

-1

Sample Input 3

10
5 1 2 3 4 5
5 2 3 4 5 6
5 3 4 5 6 7
5 4 5 6 7 8
5 5 6 7 8 9
5 6 7 8 9 10
5 7 8 9 10 1
5 8 9 10 1 2
5 9 10 1 2 3

Sample Output 3

1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

// I need some holiday
// But I don't wish that everyday is holiday
// Because I didn't bear the pain
// Because it wasn't a true freedom
//         ——『イヤホンと蝉時雨』·Orangestar

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
typedef unsigned int UI;
typedef pair<int, int> pii;

#define DEBUG(...) fprintf(stderr, __VA_ARGS__)
#define MP make_pair
#define fst first
#define snd second
#define SZ(u) ((int) (u).size())
#define ALL(u) (u).begin(), (u).end()

inline void proc_status()
{
	ifstream t("/proc/self/status");
	cerr << string(istreambuf_iterator<char>(t), istreambuf_iterator<char>()) << endl;
}

template<typename T> inline int chkmin(T &a, const T &b) { return b < a ? a = b, 1 : 0; }
template<typename T> inline int chkmax(T &a, const T &b) { return b > a ? a = b, 1 : 0; }
template<typename T> inline T sqr(const T &val) { return val * val; }

namespace fastIO
{
	const int MAX_BUFFER_SIZE = 1 << 16;

	char buffer[MAX_BUFFER_SIZE], *cur = buffer, *ed = buffer;

	inline char getc() { return cur == ed && (ed = (cur = buffer) + fread(buffer, 1, MAX_BUFFER_SIZE, stdin), cur == ed) ? EOF : *cur++; }
}
using fastIO::getc;

template<typename T> inline T read()
{
	register T sum(0), fg(1);
	register char ch(getc());
	for(; !isdigit(ch); ch = getc()) if(ch == '-') fg = -1;
	for(;  isdigit(ch); ch = getc()) sum = sum * 10 - '0' + ch;
	return sum * fg;
}

inline char *read_str(char *s)
{
	register char ch(getc());
	while(!isgraph(ch)) ch = getc();
	for(; isgraph(ch); ch = getc()) *s++ = ch;
	*s = '\0';
	return s;
}

// END tpl.

const int MAXN = (int) 1e5;

namespace FLOW
{
	const int INF = (int) 1e9;
	const int MAXV = MAXN * 2, MAXE = MAXN * 8;

	int cnt;

	inline int new_node() { return ++cnt; }

	struct edge
	{
		int v, c, nxt;

		edge() { }
		edge(int _v, int _c, int _nxt): v(_v), c(_c), nxt(_nxt) { }
	};

	edge e[MAXE * 2 + 5];
	int st[MAXV + 5], edge_cnt;

	inline void init() { cnt = 0, memset(st, -1, sizeof st), edge_cnt = 0; }
	inline int add_edge(int u, int v, int c, int type = 1)
	{
		e[edge_cnt] = edge(v, c, st[u]), st[u] = edge_cnt++;
		if(type) add_edge(v, u, 0, 0);
		return st[u];
	}

	int d[MAXV + 5];

	inline int BFS(int S, int T)
	{
		static queue<int> q;
		for(int i = 1; i <= cnt; ++i) d[i] = -1;

		d[S] = 0, q.push(S);
		while(!q.empty())
		{
			int u = q.front();
			q.pop();

			for(int i = st[u]; ~i; i = e[i].nxt)
			{
				int v = e[i].v;
				if(e[i].c > 0 && d[v] == -1) d[v] = d[u] + 1, q.push(v);
			}
		}

		return d[T] != -1;
	}

	int cur[MAXV + 5];

	inline int dfs(int u, int low, int T)
	{
		if(u == T) return low;

		int sum = 0;
		for(int &i = cur[u]; ~i; i = e[i].nxt)
		{
			int v = e[i].v, k = 0;
			if(e[i].c > 0 && d[v] == d[u] + 1 && (k = dfs(v, min(low, e[i].c), T)) > 0)
			{
				e[i].c -= k, e[i ^ 1].c += k;
				sum += k, low -= k;
				if(low == 0) break;
			}
		}
		return sum;
	}

	inline int solve(int S, int T)
	{
		int flow = 0;
		while(BFS(S, T))
		{
			for(int i = 1; i <= cnt; ++i) cur[i] = st[i];
			for(int k = dfs(S, INF, T); k > 0; k = dfs(S, INF, T)) flow += k;
		}
		return flow;
	}
}

int n;

vector<int> E[MAXN + 5];

inline void input()
{
	n = read<int>();
	for(int i = 1; i < n; ++i) for(int N = read<int>(); N--; ) E[i].push_back(read<int>());
}

int d[MAXN + 5], id[MAXN + 5];
vector<int> ids[MAXN + 5];

int fa[MAXN + 5];

inline int dfs(int u)
{
	int res = 1;
	for(auto v0 : ids[u]) if(!fa[v0])
	{
		int v = d[v0];
		fa[v0] = u;
		res += dfs(v);
	}
	return res;
}

inline void solve()
{
	FLOW::init();

	static unordered_map<int, int> eid[MAXN + 5];
	static int X[MAXN + 5], Y[MAXN + 5];

	const int S = FLOW::new_node(), T = FLOW::new_node();
	for(int i = 1; i < n; ++i) FLOW::add_edge(S, X[i] = FLOW::new_node(), 1);
	for(int i = 1; i < n; ++i) FLOW::add_edge(Y[i] = FLOW::new_node(), T, 1);

	for(int i = 1; i < n; ++i) for(auto j : E[i]) if(j != n)
		eid[i][j] = FLOW::add_edge(X[i], Y[j], 1);

	if(FLOW::solve(S, T) != n - 1) { puts("-1"); return; }

	for(int i = 1; i < n; ++i)
		for(auto j : E[i]) if(eid[i].count(j) && FLOW::e[eid[i][j]].c == 0)
		{
			d[i] = j, id[j] = i;
			break;
		}

	for(int i = 1; i < n; ++i) for(auto j : E[i]) ids[j].push_back(i);
	if(dfs(n) != n) { puts("-1"); return; }
	for(int i = 1; i < n; ++i) printf("%d %d\n", d[i], fa[i]);
}

int main()
{
#ifdef K_ON
	freopen("F.in", "r", stdin);
	freopen("F.out", "w", stdout);
#endif

	input();
	solve();

	return 0;
}