#include <algorithm>  
#include <iostream>  
#include <sstream>  
#include <string>  
#include <cstring>
#include <vector>  
#include <queue>  
#include <set>  
#include <map>  
#include <cstdio>  
#include <cstdlib>  
#include <cctype>  
#include <cmath>  
#include <list>  
#include <cassert>
#include <ctime>
#include <climits>
using namespace std;  

#define PB push_back  
#define MP make_pair  
#define SZ(v) ((int)(v).size())  
#define FOR(i,a,b) for(int i=(a);i<(b);++i)  
#define REP(i,n) FOR(i,0,n)  
#define FORE(i,a,b) for(int i=(a);i<=(b);++i)  
#define REPE(i,n) FORE(i,0,n)  
#define FORSZ(i,a,v) FOR(i,a,SZ(v))  
#define REPSZ(i,v) REP(i,SZ(v))  
typedef long long ll;
typedef unsigned long long ull;
ll gcd(ll a,ll b) { return b==0?a:gcd(b,a%b); }

const int MAXN=100000;
const int MAXESUM=200000;

const int MAXGN=2+MAXN+MAXN-1;
const int MAXGM=MAXN-1+MAXN-1+MAXESUM;

typedef struct MF {
	int n,m;
	int ghead[MAXGN],gnxt[2*MAXGM],gto[2*MAXGM]; ll gcap[2*MAXGM];
	void init(int _n) { n=_n,m=0; REP(i,n) ghead[i]=-1; }
	void addedge(int a,int b,ll c) { gnxt[2*m+0]=ghead[a],ghead[a]=2*m+0,gto[2*m+0]=b,gcap[2*m+0]=c; gnxt[2*m+1]=ghead[b],ghead[b]=2*m+1,gto[2*m+1]=a,gcap[2*m+1]=0; ++m; /*printf("%d->%d\n",a,b);*/ }
	int d[MAXGN];
	int q[MAXGN],qhead,qtail;
	int cur[MAXGN];
	ll dinic(int s,int t) {
		ll ret=0; int niter=0;
		while(true) {
			REP(i,n) d[i]=INT_MAX; qhead=qtail=0; d[s]=0,q[qhead++]=s;
			while(qtail<qhead&&d[t]==INT_MAX) { int at=q[qtail++];for(int x=ghead[at];x!=-1;x=gnxt[x]) { int to=gto[x]; if(gcap[x]==0||d[to]!=INT_MAX) continue; d[to]=d[at]+1; q[qhead++]=to; } }
			if(d[t]==INT_MAX) return ret;
			REP(i,n) cur[i]=ghead[i];
			ret+=dfs(s,t,LLONG_MAX); ++niter;
		}
	}
	ll dfs(int at,int t,ll rem) {
		ll ret=0; if(at==t) return rem;
		if(d[at]>=d[t]) return 0;
		for(;cur[at]!=-1;cur[at]=gnxt[cur[at]]) {
			int to=gto[cur[at]]; ll cap=gcap[cur[at]]; if(d[to]!=d[at]+1||cap==0) continue;
			ll now=dfs(to,t,min(cap,rem));
			rem-=now; ret+=now; if(gcap[cur[at]]!=LLONG_MAX) gcap[cur[at]]-=now; if(gcap[cur[at]^1]!=LLONG_MAX) gcap[cur[at]^1]+=now; if(rem==0) return ret;
		}
		return ret;
	}
} MF;
MF g;


int n;
vector<int> e[MAXN-1];
pair<int,int> ans[MAXN-1];

int sid,tid,lid[MAXN],rid[MAXN-1],nid;
int match[MAXN],rmatch[MAXN-1];
vector<int> who[MAXN];
bool intree[MAXN];
int q[MAXN],qhead,qtail;

bool solve() {
	nid=0; sid=nid++,tid=nid++; FOR(i,1,n) lid[i]=nid++; REP(i,n-1) rid[i]=nid++;
	g.init(nid);
	FOR(i,1,n) g.addedge(sid,lid[i],1);
	REP(j,n-1) for(int i:e[j]) if(i!=0) g.addedge(lid[i],rid[j],1);
	REP(i,n-1) g.addedge(rid[i],tid,1);
	ll flow=g.dinic(sid,tid);
	
	if(flow!=n-1) return false;
	REP(i,n) match[i]=-1; FOR(i,1,n) for(int x=g.ghead[lid[i]];x!=-1;x=g.gnxt[x]) if(g.gcap[x^1]==1&&g.gto[x]>=rid[0]) { assert(match[i]==-1); match[i]=g.gto[x]-rid[0]; } FOR(i,1,n) assert(match[i]!=-1);
	REP(i,n-1) rmatch[i]=-1; REP(i,n) if(match[i]!=-1) { assert(rmatch[match[i]]==-1); rmatch[match[i]]=i; } REP(i,n-1) assert(rmatch[i]!=-1);
	//FOR(i,1,n) { printf("%d:",i+1); REPSZ(j,e[match[i]]) printf(" %d",e[match[i]][j]+1); puts(""); }

	REP(i,n-1) REPSZ(j,e[i]) who[e[i][j]].PB(i);
	qhead=qtail=0; REP(i,n) intree[i]=false;
	intree[0]=true; q[qhead++]=0;
	while(qtail<qhead) {
		int at=q[qtail++];
		REPSZ(i,who[at]) {
			int id=who[at][i],to=rmatch[id];
			if(!intree[to]) { ans[id]=MP(at,to); intree[to]=true; q[qhead++]=to; }
		}
	}
	REP(i,n) if(!intree[i]) return false;
	return true;
}

void run() {
	scanf("%d",&n);
	REP(i,n-1) { int cnt; scanf("%d",&cnt); REP(j,cnt) { int x; scanf("%d",&x); --x; e[i].PB(x); } }
	if(!solve()) { printf("-1\n"); return; }
	REP(i,n-1) printf("%d %d\n",ans[i].first+1,ans[i].second+1);
}

int main() {
	run();
	return 0;
}


Measured memory_bytes: 33920