#include<iostream>
#include<cstdio>
#include<stdlib.h>
#include<queue>
#define ll long long
using namespace std;
typedef struct node
{
int u;
int p_n;
ll p,q;
int *element;
}Node;
Node a[100001];
int in_degree[100001];
ll gcd(ll a, ll b)
{
return b == 0 ? a : gcd(b, a % b);
}
ll lcm(ll a, ll b)
{
return a / gcd(a, b) * b;
}
void Ave_Share( int u,int v )
{
ll num,p_num_1,p_num_2;
if( a[v].p==0 )
{
if( a[u].p%a[u].p_n==0 )
{
a[v].p=a[u].p/a[u].p_n;
a[v].q=a[u].q;
}
else
{
a[v].p=a[u].p;
a[v].q=a[u].q*a[u].p_n;
}
}
else
{
p_num_1=a[u].p;
p_num_2=a[u].q*a[u].p_n;
num=lcm( p_num_2,a[v].q);
p_num_1=(num / p_num_2)*p_num_1;
a[v].p = (num / a[v].q)*a[v].p ;
a[v].q = num;
a[v].p += p_num_1;
num=gcd( a[v].p,a[v].q );
a[v].p/=num;
a[v].q/=num;
}
}
int main()
{
int n,m,i,j,d;
int index,k;
queue<int> q;
scanf("%d%d",&n,&m);
for( i=1;i<=n;i++ )
{
a[i].u=i;
scanf("%d",&d);
a[i].p_n=d;
if( d!=0 )
{
a[i].element=(int*)malloc(a[i].p_n*sizeof(int));
for( j=0;j<d;j++ )
{
scanf("%d",&a[i].element[j]);
in_degree[ a[i].element[j] ]++;
}
}
a[i].p=a[i].q=0;
}
for( i=1;i<=m;i++ )
{
a[i].p=a[i].q=1;
q.push(a[i].u);
}
while( !q.empty() )
{
index=q.front();
for( k=0;k<a[index].p_n;k++ )
{
in_degree[ a[index].element[k] ]--;
Ave_Share( index,a[index].element[k] );
if( in_degree[ a[index].element[k] ]==0 )
q.push( a[index].element[k] );
}
q.pop();
}
for( i=1;i<=n;i++ )
if( a[i].p_n==0 )
printf("%lld %lld\n",a[i].p,a[i].q);
return 0;
}