#include <bits/stdc++.h>
using namespace std;
inline int read() {
  int x = 0, fu = 0;
  char ch = getchar();
  for (; ch < 48 || ch > 57; ch = getchar()) fu |= (ch == '-');
  for (; ch > 47 && ch < 58; ch = getchar()) x = x * 10 + ch - '0';
  return fu ? -x : x;
}
const int inf = 0x3f3f3f3f;
struct Network_Flow {
  int st, ed, head[100005], eot;
  Network_Flow() { eot = 1; }
  struct edge {
    int t, nxt, w;
  } e[400005];
  void add(int u, int v, int w) {
    e[++eot] = (edge){v, head[u], w};
    head[u] = eot;
    e[++eot] = (edge){u, head[v], 0};
    head[v] = eot;
  }
  int q[100005], hd, tl, d[100005];
  bool bfs() {
    memset(d, -1, sizeof(d));
    hd = tl = 0, q[++tl] = st, d[st] = 1;
    for (int x, i; hd < tl;) {
      for (x = q[++hd], i = head[x]; i; i = e[i].nxt)
        if (d[e[i].t] == -1 && e[i].w) d[e[i].t] = d[x] + 1, q[++tl] = e[i].t;
    }
    return d[ed] != -1;
  }
  int dfs(int u, int v, int w) {
    if (u == v) return w;
    int ret = 0;
    for (int i = head[u]; i; i = e[i].nxt)
      if (e[i].w && ret < w && d[e[i].t] == d[u] + 1) {
        int flow = dfs(e[i].t, v, min(w - ret, e[i].w));
        e[i].w -= flow, e[i ^ 1].w += flow, ret += flow;
      }
    if (!ret) d[u] = -2;
    return ret;
  }
  int dinic() {
    int ret = 0;
    while (bfs()) ret += dfs(st, ed, inf);
    return ret;
  }
} wll;
int n, m, tot, M, ans[5005];
struct seg_tree {
  int Id[20005];
  void build(int id, int l, int r) {
    if (l == r) {
      Id[id] = l;
      return;
    }
    int mid = (l + r) >> 1;
    Id[id] = ++tot;
    build(id << 1, l, mid);
    build(id << 1 | 1, mid + 1, r);
    wll.add(Id[id], Id[id << 1], Id[id << 1] > m ? inf : 1);
    wll.add(Id[id], Id[id << 1 | 1], Id[id << 1 | 1] > m ? inf : 1);
  }
  void link(int id, int l, int r, int ql, int qr, int fr) {
    if (l == ql && r == qr) {
      wll.add(fr, Id[id], 1);
      return;
    }
    int mid = (l + r) >> 1;
    if (mid >= qr)
      link(id << 1, l, mid, ql, qr, fr);
    else if (mid < ql)
      link(id << 1 | 1, mid + 1, r, ql, qr, fr);
    else
      link(id << 1, l, mid, ql, mid, fr),
          link(id << 1 | 1, mid + 1, r, mid + 1, qr, fr);
  }
  vector<int> Empty;
  vector<int> getans(int id, int l, int r) {
    if (l == r) return Empty;
    int mid = (l + r) >> 1;
    vector<int> L = getans(id << 1, l, mid);
    vector<int> R = getans(id << 1 | 1, mid + 1, r);
    vector<int> now;
    set_union(L.begin(), L.end(), R.begin(), R.end(), back_inserter(now));
    for (int i = wll.head[Id[id]]; i; i = wll.e[i].nxt) {
      if (wll.e[i].t <= m && wll.e[i].w == 0) now.push_back(wll.e[i].t);
    }
    for (int i = wll.head[Id[id]]; i; i = wll.e[i].nxt) {
      if (wll.e[i].t > M && wll.e[i].w)
        ans[now[now.size() - 1]] = wll.e[i].t - M, now.pop_back();
    }
    return now;
  }
} s;
int iD[5005], op0[5005], tp0, op2[5005], tp2, from[5005];
int main() {
  n = read(), tot = m = read();
  s.build(1, 1, m), M = tot;
  wll.st = M + n + 1, wll.ed = M + n + 2;
  for (int i = 1; i <= m; i++) wll.add(i, wll.ed, 1);
  for (int i = 1, op, x, y, z; i <= n; i++) {
    op = read(), iD[i] = ++tot, wll.add(wll.st, tot, op == 2 ? 2 : 1);
    from[i] = wll.eot - 1;
    if (!op) {
      op0[++tp0] = i, x = read();
      while (x--) y = read(), wll.add(tot, y, 1);
    } else if (op ^ 2) {
      op0[++tp0] = i, x = read(), y = read(), s.link(1, 1, m, x, y, tot);
    } else {
      x = read(), y = read(), z = read(), op2[++tp2] = i;
      wll.add(tot, x, 1), wll.add(tot, y, 1), wll.add(tot, z, 1);
    }
  }
  printf("%d\n", wll.dinic());
  for (int i = 1; i <= tp0; i++)
    for (int j = wll.head[iD[op0[i]]]; j; j = wll.e[j].nxt)
      if (wll.e[j].t <= m && wll.e[j ^ 1].w) ans[wll.e[j].t] = op0[i];
  s.getans(1, 1, m);
  for (int I = 1, i = op2[I]; I <= tp2; I++, i = op2[I]) {
    for (int j = wll.head[iD[i]]; j; j = wll.e[j].nxt)
      if (wll.e[j].t <= m && !wll.e[j].w) ans[wll.e[j].t] = i;
    if (wll.e[from[i]].w == 1)
      for (int j = wll.head[iD[i]]; j; j = wll.e[j].nxt)
        if (wll.e[j].t != wll.st && wll.e[j].w) {
          ans[wll.e[j].t] = i;
          break;
        }
  }
  for (int i = 1; i <= m; i++)
    if (ans[i]) printf("%d %d\n", ans[i], i);
  return 0;
}
