#include<bits/stdc++.h>
#define int long long
using namespace std;
struct Node{
int z,m;
};
Node fs[100005];
vector<int>l[100005];
int s[100005];
Node yf(Node fs){//约分
int z=fs.z;
for(int i=2;i*i<=z;i++){
while(fs.z%i==0 && fs.m%i==0){
fs.z/=i;
fs.m/=i;
}
while(fs.z%(z/i)==0 && fs.m%(z/i)==0){
fs.z/=(z/i);
fs.m/=(z/i);
}
}
while(fs.z%z==0 && fs.m%z==0){
fs.z/=z;
fs.m/=z;
}
return fs;
}
void add(int i,Node f){//将i点的水加上f
f.z*=fs[i].m;
fs[i].z*=f.m;
fs[i].m*=f.m;
fs[i].z+=f.z;
fs[i]=yf(fs[i]);
return;
}
void main1(){
int n,m,d,v;
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>d;
for(int j=0;j<d;j++){
cin>>v;
s[v]++;
l[i].push_back(v);
}
}
queue<int>q;
for(int i=1;i<=n;i++){
fs[i].z=0;
fs[i].m=1;
if(s[i]==0){
fs[i].z=1;
q.push(i);
}
}
while(q.size()){
int p=q.front();
q.pop();
Node f=yf({fs[p].z,fs[p].m*l[p].size()});
for(int i=0;i<l[p].size();i++){
add(l[p][i],f);
s[l[p][i]]--;
if(s[l[p][i]]==0){
q.push(l[p][i]);
}
}
}
for(int i=1;i<=n;i++){
if(l[i].size()==0){
cout<<fs[i].z<<' '<<fs[i].m<<endl;
}
}
return;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t=1;
//cin>>t;
while(t--){
main1();
}
return 0;
}
全TLE……