RT
#include <cstdio>
#include <algorithm>
#include <cctype>
#include <queue>
using namespace std;
int head[601000], nxt[601000], to[601000], cnt, d[600010], p[600010], o[600010];
void add(int x, int y) {
nxt[++ cnt] = head[x];
head[x] = cnt;
to[cnt] = y;
p[y] ++;
o[x] ++;
}
int n, m, ot[10005], it[10005], ocnt;
void read(int &x) {
x = 0;
int w = 1;
char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-') {
w = -1;
}
ch = getchar();
}
while (isdigit(ch)) {
x = x * 10 + (ch - '0');
ch = getchar();
}
x *= w;
}
queue<int> q;
struct Node {
long long a, b;
} tot[501000];
long long gcd(long long a,long long b){while(b!=0){long long t=b;b=a%b;a=t;}return a;}
void bfs() {
for (int i = 1; i <= n; i ++) {
if (i <= m) {
tot[i] = (Node) {1, 1};
q.push(i);
} else {
tot[i] = (Node) {0, 1};
}
}
while (!q.empty()) {
int x = q.front(); q.pop();
// printf("f %d\n", x);
if (o[x])
tot[x].b *= (long long) o[x];
for (int i = head[x]; i; i = nxt[i]) {
int y = to[i];
// printf("update %d by %d\n", y, x);
// tot[y] += tot[x] / (long long) o[x];
// printf("%d %d\n", o[x], x);
long long t1 = gcd(tot[x].b, tot[y].b);
// printf("t %lld tot %lld %lld %d %d\n", t1, tot[x].b, tot[y].b, x, y);
long long res1 = tot[x].b / t1 * tot[y].b;
long long res2 = tot[y].b / t1 * tot[x].a + tot[x].b / t1 * tot[y].a;
long long t2 = gcd(res1, res2);
tot[y].a = res2 / t2;
tot[y].b = res1 / t2;
// printf("%d %d %lld %lld\n", x, y, tot[y].a, tot[y].b);
-- p[y];
if (p[y] == 0) {
q.push(y);
}
}
}
}
int main() {
// freopen("water.in", "r", stdin);
// freopen("water.out", "w", stdout);
//
read(n), read(m);
for (int i = 1; i <= n; i ++) {
read(d[i]);
for (int j = 1; j <= d[i]; j ++) {
int y;
read(y);
add(i, y);
}
if (d[i] == 0) {
ot[++ ocnt] = i;
}
}
bfs();
for (int i = 1; i <= ocnt; i ++) {
printf("%lld %lld\n", tot[ot[i]].a, tot[ot[i]].b);
}
return 0;
}