#include <iostream>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <string>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define mp push_back
int n;
const int N = 100010;
const int M = 10000100;
struct Edge
{
int to,next;
}edge[M];
int H[N];
int low[N];
int vis[N];
int len;
struct Bridge
{
int u,v;
}bridge[M];
int cmp(Bridge a,Bridge b)
{
if(a.u == b.u)
return a.v < b.v;
return a.u < b.u;
}
int bricnt;
int times;
void addedge(int u,int v)
{
edge[len].to = v;
edge[len].next = H[u];
H[u] = len ++;
}
void dfs(int st,int fa)
{
low[st] = vis[st] = ++ times;
for(int ei=H[st];ei!=-1;ei=edge[ei].next)
{
int v = edge[ei].to;
if(v == fa) continue;
if(vis[v] == 0)
{
dfs(v,st);
low[st] = min(low[st],low[v]);
if(low[v] > vis[st])
{
bridge[bricnt].u = st;
bridge[bricnt].v = v;
if(bridge[bricnt].u > bridge[bricnt].v)
{
swap(bridge[bricnt].u,bridge[bricnt].v);
}
bricnt ++;
}
}
else
{
if(v != fa)
low[st] = min(low[st],low[v]);
}
}
}
void solve()
{
for(int i=1;i<=n;i++)
{
if(vis[i] == 0)
{
dfs(i,-1);
}
}
sort(bridge,bridge+bricnt,cmp);
printf("%d critical links\n", bricnt);
for (int i = 0; i < bricnt; ++i)
{
printf("%d - %d\n", bridge[i].u - 1, bridge[i].v - 1);
}
printf("\n");
}
int main()
{
while(scanf("%d",&n) != EOF)
{
len = 0;
memset(H,-1,sizeof(H));
memset(low,0,sizeof(low));
memset(vis,0,sizeof(vis));
bricnt = 0;
times = 0;
for(int i=0;i<n;i++)
{
int u,v,m;
scanf("%d (%d)",&u,&m);
u ++;
for(int j=0;j<m;j++)
{
scanf("%d",&v);
v ++;
addedge(u,v);
}
}
solve();
}
return 0;
}