#include<iostream>
#include<cstdio>
#include<queue>
#include<utility>
#include<algorithm>
#include<cstring>
using namespace std;
long long int gcd(long long int a,long long int b){
if(a%b==0) return b;
else return gcd(b,a%b);
}
long long int lcm(long long int a,long long int b){
return a*b/gcd(a,b);
}
struct Water{
long long int p,q;
Water operator +(const Water a)const{
Water r;
r.q=lcm(q,a.q);
r.p=p*r.q/q+a.p*r.q/a.q;
r.p/=gcd(r.p,r.q);
r.q/=gcd(r.p,r.q);
return r;
}
Water operator /(const long long int n)const{
Water r;
r.q*=n;
r.p/=gcd(r.p,r.q);
r.q/=gcd(r.p,r.q);
return r;
}
bool operator <(const Water a)const{
long double _t,_a;
_a=1.0*a.p/a.q;_t=1.0*p/q;
return _t<_a;
}
}water[100001];
struct Edge{
int next,to;
}edge[500001];
int head[100001],n,m,rd[100001],cd[100001],out[10],cnt=0,d,tmp,outed=0;
bool if_is_out[100001];
queue<pair<Water,long long int> >q;
int main()
{
memset(head,-1,sizeof(head));
memset(if_is_out,false,sizeof(if_is_out));
cin>>n>>m;
for(int i=1;i<=n;++i)
{
cin>>d;
for(int j=0;j<d;++j)
{
cin>>tmp;
edge[cnt].next=head[i];
edge[cnt].to=tmp;
head[i]=cnt;
++cnt;
++rd[tmp];
++cd[i];
}
}
cnt=0;
for(int i=1;i<=n;i++)
{
if(rd[i]==0){q.push(make_pair(Water{1,1},i));water[i]=Water{1,1};}
if(cd[i]==0){out[cnt]=i;++cnt;}
}
while(!q.empty())
{
pair<Water,long long int>t=q.front();
q.pop();
if(cd[t.second]==0)continue;
for(int i=head[t.second];i!=-1;i=edge[i].next)
{
water[edge[i].to]=water[edge[i].to]+t.first/cd[t.second];
--rd[edge[i].to];
if(rd[edge[i].to]==0)q.push(make_pair(water[edge[i].to],edge[i].to));
}
}
for(int i=0;i<m;i++)cout<<water[out[i]].p<<" "<<water[out[i]].q<<"\n";
}