#include <bits/stdc++.h>
using namespace std;
int n, m, S, T, ans, rt, cnt, lc[20000], rc[20000], pos[20000];
int tag[20000], A[20000][3], from[20000], dep[20000], q[20000];
int k = 1, la[20000], ff[400000], cur[20000], ss[20000];
struct node {
  int a, b, c;
} e[400000];
void add(int a, int b, int c) {
  e[++k] = (node){a, b, c};
  ff[k] = la[a];
  la[a] = k;
  e[++k] = (node){b, a, 0};
  ff[k] = la[b];
  la[b] = k;
}
int dfs(int x, int flow) {
  if (x == T) return flow;
  int res = 0, tmp;
  for (int a = cur[x]; a && flow; a = ff[a]) {
    cur[x] = a;
    if (dep[e[a].b] == dep[x] + 1 && e[a].c) {
      tmp = dfs(e[a].b, min(flow, e[a].c));
      e[a].c -= tmp;
      e[a ^ 1].c += tmp;
      res += tmp;
      flow -= tmp;
    }
  }
  if (!res) dep[x] = -1;
  return res;
}
bool bfs() {
  memset(dep, 0, sizeof(dep));
  for (int i = S; i <= T; i++) cur[i] = la[i];
  int l = 1, r = 2;
  q[1] = S;
  dep[S] = 1;
  while (l < r) {
    int x = q[l];
    l++;
    for (int a = la[x]; a; a = ff[a])
      if (!dep[e[a].b] && e[a].c) q[r] = e[a].b, dep[q[r]] = dep[x] + 1, r++;
  }
  return dep[T];
}
void build(int &x, int l, int r, int pre) {
  if (!x) x = ++cnt;
  if (pre) add(pre, x, r - l + 1);
  if (l == r) {
    pos[l] = x;
    return;
  }
  int mid = l + r >> 1;
  build(lc[x], l, mid, x);
  build(rc[x], mid + 1, r, x);
}
void solve(int x, int l, int r, int ql, int qr, int S) {
  if (ql <= l && r <= qr) {
    add(S, x, 1);
    return;
  }
  int mid = l + r >> 1;
  if (ql <= mid) solve(lc[x], l, mid, ql, qr, S);
  if (qr > mid) solve(rc[x], mid + 1, r, ql, qr, S);
}
int find(int x, int flow, int pos) {
  if (x == T) return flow;
  int res = 0, tmp;
  for (int a = la[x]; a; a = ff[a])
    if (!(a & 1) && e[a ^ 1].c) {
      tmp = find(e[a].b, min(flow, e[a ^ 1].c), pos);
      e[a ^ 1].c -= tmp;
      e[a].c += tmp;
      res += tmp;
      flow -= tmp;
      if (e[a].b == T) from[x] = pos;
    }
  return res;
}
int main() {
  int tp, x, len, l, r, a, b, c;
  scanf("%d%d", &n, &m);
  cnt = n;
  build(rt, 1, m, 0);
  T = cnt + 1;
  for (int i = 1; i <= n; i++) {
    scanf("%d", &tp);
    cnt++;
    if (tp == 0) {
      scanf("%d", &len);
      add(S, i, 1);
      for (int j = 1; j <= len; j++) scanf("%d", &x), add(i, pos[x], 1);
    }
    if (tp == 1) {
      scanf("%d%d", &l, &r);
      add(S, i, 1);
      solve(rt, 1, m, l, r, i);
    }
    if (tp == 2) {
      scanf("%d%d%d", &a, &b, &c);
      tag[i] = 1;
      A[i][0] = a;
      A[i][1] = b;
      A[i][2] = c;
      add(S, i, 2);
      add(i, pos[a], 1);
      add(i, pos[b], 1);
      add(i, pos[c], 1);
    }
  }
  for (int i = 1; i <= m; i++) add(pos[i], T, 1);
  while (bfs()) ans += dfs(S, 1050000000);
  for (int a = la[S]; a; a = ff[a])
    if (e[a ^ 1].c) find(e[a].b, e[a ^ 1].c, e[a].b);
  for (int i = 1; i <= m; i++) ss[from[pos[i]]]++;
  for (int i = 1; i <= n; i++)
    if (tag[i] && ss[i] == 1) {
      int flag = 0;
      for (int j = 0; j <= 2; j++)
        if (from[pos[A[i][j]]] && from[pos[A[i][j]]] != i) {
          from[pos[A[i][j]]] = i;
          flag = 1;
          break;
        }
      if (flag) continue;
      for (int j = 0; j <= 2; j++) from[pos[A[i][j]]] = 0;
      ans--;
    }
  printf("%d\n", ans);
  for (int i = 1; i <= m; i++)
    if (from[pos[i]]) printf("%d %d\n", from[pos[i]], i);
  return 0;
}
