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

using namespace std;
const int MAXN = 5010;

vector<int> v[MAXN], kvb[MAXN];
vector<pair<int,int> > tc[MAXN];
int outdg[MAXN];
int n, sccn, dfsn;
int white = 0, grey = 1, black = 2;
int mark[MAXN];
int order[MAXN], low[MAXN], scc[MAXN], prev[MAXN];
int b[MAXN][MAXN];	// grane
int t[MAXN][MAXN];


stack<int> s;
FILE* f;

void init(){
     freopen("rostilj.in","r", stdin);
     f = fopen("rostilj.out","w");
}

void read(){
	int k;
    scanf("%d",&n);
    for (int i = 0; i < n; i++){
        scanf("%d",&k);
        outdg[i] = k;
        for (int j = 0; j < k; j++){
            int a;
            scanf("%d", &a);
            v[i].push_back(a-1);
        }
    }
}

void dfs_strongly(int k){
	s.push(k);
	low[k] = order[k] = dfsn++;
	mark[k] = grey;
	for (int i = 0; i < v[k].size(); i++)
		if (mark[v[k][i]] == white){
			dfs_strongly(v[k][i]);
			low[k] = min(low[k], low[v[k][i]]);
		}
		else{
			if (scc[v[k][i]]==-1) low[k] = min(low[k], order[v[k][i]]);
		}
	if (low[k] == order[k]){
		int x;
		do{
			x = s.top();
			s.pop();
			scc[x] = sccn;
		} while(x != k);
		sccn++;
	}
}

void finish(int a, int b){
	fprintf(f, "%d %d\n", a+1, b+1);
	fclose(stdin);
	fclose(f);
	exit(0);
}

void divide_components(){
	memset(mark, 0, sizeof(mark));
	memset(scc, -1, sizeof(scc));
	sccn = 0; dfsn = 0;
	for (int i = 0; i < n; i++)
		if (!mark[i]){
			dfs_strongly(i);
		}
	memset(outdg, 0, sizeof(outdg));
	memset(b, 0, sizeof(b));
	for(int i = 0; i < n; i++)
		for (int j = 0; j < v[i].size(); j++)
			if (!b[scc[i]][scc[v[i][j]]] && scc[i]!=scc[v[i][j]]){
				b[scc[i]][scc[v[i][j]]] = 1;
				kvb[scc[v[i][j]]].push_back(scc[i]);
				outdg[scc[i]]++;
			}
			else if (scc[i]!=scc[v[i][j]]) finish(i,v[i][j]);
}

int common_ancestor(int a, int b, int* prev){
	int m1[MAXN];
	memset(m1,0,sizeof(m1));
	while(1){
		if (a>-1){
			if (m1[a])
				return a;
			m1[a] = 1;
			a = prev[a];
		}							
		if (b>-1){
			if (m1[b])
				return b;
			m1[b] = 1;
			b = prev[b];
		}
	}
}


int dfs_inside(int k){
	order[k] = dfsn++;
	mark[k] = grey;
	int up = -1;
	for (int i = 0; i < v[k].size(); i++)
		if (scc[v[k][i]] == scc[k])
			if (mark[v[k][i]] == white){
				prev[v[k][i]] = k;
				int up1 = dfs_inside(v[k][i]);
				if (up1 >= 0)
					if (order[up1]<order[k])
						if (up < 0)
							up = up1;
						else 
							if (order[up]>order[up1])
								finish(k, up);
							else
								finish(k,up1);
				
			} else if (mark[v[k][i]]==grey){
				if (up < 0)
					up = v[k][i];
				else
					if (order[up]>order[v[k][i]])
						finish(k,up);
					else
						finish(k,v[k][i]);
			} else{
				finish(common_ancestor(k,v[k][i], prev),v[k][i]);
			}
	mark[k] = black;
	return up;
}

void find_in_components(){
	memset(mark, 0, sizeof(mark));
	memset(order, 0, sizeof(order));
	memset(prev, -1, sizeof(prev));
	dfsn = 1;
	for (int i = 0; i < n; i++)
		if (!mark[i])
			dfs_inside(i);
}

void finish_components(int a, int b, pair<int,int> d){
	int x, y, i, found = 0;
	for (x=0; x < n && !found; x++){
		if (scc[x] == a){
			for (i = 0; i < v[x].size() && scc[v[x][i]]!=b; i++);
      		if (i < v[x].size()) found = 1;
        }
    }
    found = 0;
	for (y=0; y < n && !found; y++){
		if (scc[y] == d.second){
			for (i = 0; i < v[y].size() && scc[v[y][i]]!=d.first; i++);
		    if (i < v[y].size()) found = 1;
        }
    }
	y = v[y-1][i];
	finish(x-1,y);
}

void find_among_components(){
	int i;
	queue<int> q;
	int order[sccn], topsortnum = 0;
	memset(t,0,sizeof(t));
	for (i = 0; i < sccn; i++)
		if (outdg[i] == 0)
			q.push(i);
	while(q.size()>0){
		int x = q.front();
		q.pop();
		order[x] = topsortnum++;
		pair<int,int> dest(-1,-1); int source = -1;
		for (i = 0; i < kvb[x].size(); i++){
			int y = kvb[x][i];
			pair<int,int> p(x,y);
			tc[x].push_back(p);
			if (--outdg[y] == 0)
				q.push(y);
			for (int j = 0; j < tc[x].size(); j++){
				if (t[y][tc[x][j].first] == 1)
					if (dest.first == -1)
						{dest = tc[x][j];source=y;}
					else
						{dest = order[dest.first]>order[tc[x][j].first]?dest:tc[x][j];source=y;}
				t[y][tc[x][j].first] = 1;
				tc[y].push_back(tc[x][j]);
			}
			tc[x].pop_back();
		}
		if (dest.first != -1) finish_components(source,x,dest);
	}	
}

int main(){
	 init();
     read();
	 divide_components();
	 find_in_components();
	 find_among_components();
	 for (int i = 0; i < n ;i++)
		 printf("%d\n",scc[i]);
	 return 0;  
}
