// Author -- Frame

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<iostream>

#define lowbit(x) ((x)&(-x))
#define Finline __inline__ __attribute__ ((always_inline))
#define DEBUG fprintf(stderr,"Running on Line %d in Function %s\n",__LINE__,__FUNCTION__)

typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;

const int inf=0x3f3f3f3f,Inf=0x7fffffff;
const ll INF=0x7fffffffffffffff;
const double eps=1e-10;

template <typename _Tp>_Tp gcd(const _Tp &a,const _Tp &b){return (!b)?a:gcd(b,a%b);}
template <typename _Tp>Finline _Tp abs(const _Tp &a){return a>=0?a:-a;}
template <typename _Tp>Finline _Tp max(const _Tp &a,const _Tp &b){return a<b?b:a;}
template <typename _Tp>Finline _Tp min(const _Tp &a,const _Tp &b){return a<b?a:b;}
template <typename _Tp>Finline void chmax(_Tp &a,const _Tp &b){(a<b)&&(a=b);}
template <typename _Tp>Finline void chmin(_Tp &a,const _Tp &b){(b<a)&&(a=b);}
template <typename _Tp>Finline bool _cmp(const _Tp &a,const _Tp &b){return abs(a-b)<=eps;}
template <typename _Tp>Finline void read(_Tp &x)
{
	register char ch(getchar());
	bool f(false);
	while(ch<48||ch>57) f|=ch==45,ch=getchar();
	x=ch&15,ch=getchar();
	while(ch>=48&&ch<=57) x=(((x<<2)+x)<<1)+(ch&15),ch=getchar();
	if(f) x=-x;
}
template <typename _Tp,typename... Args>Finline void read(_Tp &t,Args &...args)
{
	read(t);read(args...);
}
Finline int read_str(char *s)
{
	register char ch(getchar());
	while(ch==' '||ch=='\r'||ch=='\n') ch=getchar();
	register char *tar=s;
	*tar=ch,ch=getchar();
	while(ch!=' '&&ch!='\r'&&ch!='\n'&&ch!=EOF) *(++tar)=ch,ch=getchar();
	return tar-s+1;
}

const int N=200015;
template<typename _Tp>
class flow{
public:
	struct edge{
		int v,nxt;
		_Tp w;
	}c[N<<3];
	int front[N],edge_cnt;
	Finline flow(){memset(front,255,sizeof(front)),edge_cnt=-1;}
	int cur[N],dep[N],S,T;
	int _q[N],_l,_r;
	int node_cnt;
	Finline void add(int u,int v,_Tp w)
	{
		c[++edge_cnt]=(edge){v,front[u],w},front[u]=edge_cnt;
		c[++edge_cnt]=(edge){u,front[v],0},front[v]=edge_cnt;
	}
	bool bfs()
	{
		memset(dep,255,(node_cnt+3)<<2);
		memcpy(cur,front,(node_cnt+3)<<2);
		dep[S]=0;
		_q[_l=_r=1]=S;
		while(_l!=_r+1)
		{
			int x=_q[_l++];
			for(int i=front[x];~i;i=c[i].nxt)
			{
				if(c[i].w&&!~dep[c[i].v])
				{
					dep[c[i].v]=dep[x]+1;
					_q[++_r]=c[i].v;
				}
			}
		}
		return ~dep[T];
	}
	_Tp dfs(int x,int flow)
	{
		if(x==T||!flow) return flow;
		_Tp f=0,rf;
		for(int &i=cur[x];~i;i=c[i].nxt)
		{
			if(dep[c[i].v]==dep[x]+1&&(rf=dfs(c[i].v,min(flow,c[i].w))))
			{
				flow-=rf,f+=rf;
				c[i].w-=rf,c[i^1].w+=rf;
				if(!flow) return f;
			}
		}
		return f;
	}
	_Tp dinic()
	{
		_Tp ans=0;
		while(bfs()) ans+=dfs(S,inf);
		// inf changes when _Tp != int
		return ans;
	}
	bool vis[N];
	int to[N];
	int n;
	std::pair<int,int> ans[N];
	int cnt=0;
	void dfs(int x)
	{
		for(int i=front[x];~i;i=c[i].nxt)
		{
			if(c[i].v<n+n&&!vis[c[i].v-n])
			{
				++cnt;
				ans[c[i].v-n]=std::make_pair(x,to[c[i].v-n]);
				vis[c[i].v-n]=true;
				dfs(to[c[i].v-n]);
			}
		}
	}
	void solve(int _n)
	{
		n=_n;
		int root=0;
		for(int i=front[S];~i;i=c[i].nxt)
		{
			if(c[i].w)
			{
				root=c[i].v;
				break;
			}
		}
		for(int i=1;i<n;++i)
		{
			for(int _=front[i+n];~_;_=c[_].nxt)
			{
				if(c[_].v<=n&&c[_].w)
				{
					to[i]=c[_].v;
					break;
				}
			}
		}
		dfs(root);
		if(cnt!=n-1)
		{
			printf("-1\n");
		}
		else
		{
			for(int i=1;i<n;++i) printf("%d %d\n",ans[i].first,ans[i].second);
		}
	}
};
flow<int> F;
int main()
{
	int n;
	read(n);
	int x,y;
	F.S=n+n,F.T=n+n+1;
	F.node_cnt=n+n+1;
	for(int i=1;i<n;++i)
	{
		read(x);
		for(int j=1;j<=x;++j)
		{
			read(y);
			F.add(y,i+n,1);
		}
		F.add(i+n,F.T,1);
		F.add(F.S,i,1);
	}
	F.add(F.S,n,1);
	int ans=F.dinic();
	if(ans!=n-1)
	{
		printf("-1\n");
		return 0;
	}
	F.solve(n);
	return 0;
}


Measured memory_bytes: 18816