#include <bits/stdc++.h>
using namespace std;
void rd(int &t) {
  t = 0;
  char p = getchar();
  while (p == ' ' || p == '\n') p = getchar();
  do {
    (t *= 10) += p - '0';
    p = getchar();
  } while (p >= '0' && p <= '9');
}
const int N = 500005, M = N << 2, inf = 1 << 30;
int to[M], nxt[M], len[M], inv[M], fir[N], cur[N], idx[N];
int Q[N], lev[N], pos[N], tot[N], n, m, cnt, ecnt, S, T;
bool vis[N];
struct qst {
  int opt, l, r, k, a, b, c;
} q[N];
void ae(int u, int v, int w) {
  to[++ecnt] = v;
  nxt[ecnt] = fir[u];
  len[ecnt] = w;
  inv[ecnt] = ecnt + 1;
  fir[u] = ecnt;
  to[++ecnt] = u;
  nxt[ecnt] = fir[v];
  len[ecnt] = 0;
  inv[ecnt] = ecnt - 1;
  fir[v] = ecnt;
}
struct Seg {
  void build(int rt, int l, int r) {
    if (l == r) {
      idx[rt] = l;
      return;
    }
    idx[rt] = ++cnt;
    int mid = l + r >> 1;
    build(rt << 1, l, mid);
    build(rt << 1 | 1, mid + 1, r);
    ae(idx[rt], idx[rt << 1], inf);
    ae(idx[rt], idx[rt << 1 | 1], inf);
  }
  void link(int rt, int l, int r, int ql, int qr, int id) {
    if (ql <= l && r <= qr) {
      ae(id, idx[rt], 1);
      return;
    }
    int mid = l + r >> 1;
    if (ql <= mid) link(rt << 1, l, mid, ql, qr, id);
    if (qr > mid) link(rt << 1 | 1, mid + 1, r, ql, qr, id);
  }
} seg;
bool make_level() {
  int u, v, w, l, r, i;
  memset(vis, false, sizeof(vis));
  for (i = S; i <= T; ++i) cur[i] = fir[i];
  Q[l = r = 1] = S;
  vis[S] = true;
  while (l <= r) {
    u = Q[l++];
    for (i = fir[u]; i; i = nxt[i]) {
      v = to[i];
      w = len[i];
      if (w && !vis[v]) {
        vis[Q[++r] = v] = true;
        lev[v] = lev[u] + 1;
      }
    }
  }
  return vis[T];
}
int dinic(int u, int lim) {
  if (u == T) return lim;
  int ret = 0, tmp, v, w, i;
  for (i = cur[u]; i; i = nxt[i]) {
    v = to[i];
    w = len[i];
    if (w && lev[v] == lev[u] + 1) {
      tmp = dinic(v, min(w, lim));
      len[i] -= tmp;
      len[inv[i]] += tmp;
      lim -= tmp;
      ret += tmp;
      if (!lim) {
        cur[u] = i;
        return ret;
      }
    }
  }
  cur[u] = 0;
  return ret;
}
void work(int u, int &x, int pre) {
  if (x) return;
  if (u > m && u <= n + m) {
    x = u - m;
    return;
  }
  int i, v, w;
  for (i = fir[u]; i; i = nxt[i]) {
    v = to[i];
    w = len[i];
    if (v != pre && w) {
      work(v, x, u);
      --len[i];
      return;
    }
  }
}
int main() {
  int x, v, w, ans = 0, i, j;
  rd(n);
  rd(m);
  cnt = n + m;
  S = 0;
  T = 55555;
  seg.build(1, 1, m);
  for (i = 1; i <= n; ++i) {
    scanf("%d", &q[i].opt);
    if (!q[i].opt) {
      scanf("%d", &q[i].k);
      ae(S, i + m, 1);
      for (j = 1; j <= q[i].k; ++j) {
        scanf("%d", &x);
        ae(i + m, x, 1);
      }
    } else if (q[i].opt == 1) {
      ae(S, i + m, 1);
      scanf("%d%d", &q[i].l, &q[i].r);
      seg.link(1, 1, m, q[i].l, q[i].r, i + m);
    } else if (q[i].opt == 2) {
      ae(S, i + m, 2);
      scanf("%d%d%d", &q[i].a, &q[i].b, &q[i].c);
      ae(i + m, q[i].a, 1);
      ae(i + m, q[i].b, 1);
      ae(i + m, q[i].c, 1);
    }
  }
  for (i = 1; i <= m; ++i) ae(i, T, 1);
  while (make_level()) ans += dinic(S, inf);
  printf("%d\n", ans);
  for (i = fir[T]; i; i = nxt[i]) {
    v = to[i];
    w = len[i];
    if (w) work(v, pos[v], T);
  }
  for (i = 1; i <= m; ++i) ++tot[pos[i]];
  for (i = 1; i <= n; ++i)
    if (q[i].opt == 2 && tot[i] == 1) {
      if (pos[q[i].a] != i)
        pos[q[i].a] = i;
      else
        pos[q[i].b] = i;
    }
  for (i = 1; i <= m; ++i)
    if (pos[i]) printf("%d %d\n", pos[i], i);
  return 0;
}
