#include <bits/stdc++.h>
using std::cin;
using std::cout;
using std::endl;
using std::max;
using std::min;
using std::pair;
using std::priority_queue;
using std::queue;
using std::set;
using std::sort;
using std::vector;
template <typename T>
bool chmin(T &a, const T &b) {
  return a > b ? a = b, true : false;
}
template <typename T>
bool chmax(T &a, const T &b) {
  return a < b ? a = b, true : false;
}
const int maxN = 100000;
const int maxM = 100000;
const long long FINITE = 314000000;
const long long INF = 0x3f3f3f3f3f3f3f3f;
int n, m;
vector<int> deg[maxN];
vector<long long> val[maxN];
vector<vector<int> > G[maxN];
vector<pair<int, int> > T[maxN];
long long f[maxN], g[maxN];
bool canInf[maxN];
const int NOT = 0;
const int ED = -1;
const int ING = 1;
int status[maxN];
void DFS(int u) {
  status[u] = ING;
  for (auto &l : G[u]) {
    bool tmp = false;
    for (int &v : l) {
      if (f[v] == -1) goto FAIL;
      switch (status[v]) {
        case NOT:
          DFS(v);
        case ED:
          tmp = tmp || canInf[v];
          break;
        case ING:
          tmp = true;
          break;
      }
    }
    canInf[u] = canInf[u] || tmp;
  FAIL : {}
  }
  status[u] = ED;
}
priority_queue<pair<long long, int>, vector<pair<long long, int> >,
               std::greater<pair<long long, int> > >
    pq;
bool vis[maxN];
void Dijkstra() {
  for (int u = 0; u <= n; ++u) vis[u] = false, f[u] = INF;
  pq.push(pair<long long, int>(1, 0));
  f[0] = 1;
  while (!pq.empty()) {
    int u = pq.top().second;
    pq.pop();
    if (vis[u])
      continue;
    else
      vis[u] = true;
    for (auto &p : T[u]) {
      val[p.first][p.second] += f[u];
      if (--deg[p.first][p.second] == 0 &&
          (f[p.first] > val[p.first][p.second])) {
        f[p.first] = val[p.first][p.second];
        chmin(f[p.first], FINITE);
        pq.push(pair<long long, int>(f[p.first], p.first));
      }
    }
  }
  for (int u = 1; u <= n; ++u)
    if (f[u] == INF) f[u] = g[u] = -1;
}
void initialize() {
  scanf("%d%d", &m, &n);
  vector<int> rec;
  for (int kase = 1; kase <= m; ++kase) {
    int u, c;
    scanf("%d%d", &u, &c);
    rec.clear();
    deg[u].push_back(c);
    val[u].push_back(0);
    while (c--) {
      int v;
      scanf("%d", &v);
      if (v == -1) v = 0;
      rec.push_back(v);
      T[v].push_back(pair<int, int>(u, G[u].size()));
    }
    G[u].push_back(rec);
  }
  f[0] = g[0] = 1;
  for (int u = 1; u <= n; ++u) f[u] = INF, g[u] = 0;
  Dijkstra();
  for (int u = 0; u <= n; ++u) canInf[u] = false, status[u] = NOT;
  for (int u = 0; u <= n; ++u)
    if (status[u] == NOT && g[u] == 0) DFS(u);
  for (int u = 1; u <= n; ++u)
    if (canInf[u]) g[u] = -2;
}
void dp(int u) {
  if (g[u]) return;
  long long &ans = g[u];
  for (auto &l : G[u]) {
    long long cur = 0;
    for (int v : l) {
      dp(v);
      if (g[v] == -1) goto BYEBYE;
      cur += g[v];
    }
    chmax(ans, cur);
  BYEBYE : {}
  }
  chmin(ans, FINITE);
}
int main() {
  initialize();
  for (int u = 1; u <= n; ++u) dp(u);
  for (int u = 1; u <= n; ++u) {
    printf("%lld %lld\n", f[u], g[u]);
  }
  return 0;
}
