#include <bits/stdc++.h>
using namespace std;
int read() {
  char ch = getchar();
  int x = 0, fl = 1;
  for (; !isdigit(ch); ch = getchar())
    if (ch == '-') fl = -1;
  for (; isdigit(ch); ch = getchar()) x = (x << 3) + (x << 1) + (ch - '0');
  return x * fl;
}
const int N = 30005;
const int M = 10000005;
const int INF = 1e9;
int n, m, _, lev[N], s, t;
int ver[M], cap[M], nxt[M], fst[N], cur[N], tot;
void addedge(int x, int y, int c) {
  ver[++tot] = y;
  cap[tot] = c;
  nxt[tot] = fst[x];
  fst[x] = tot;
  ver[++tot] = x;
  cap[tot] = 0;
  nxt[tot] = fst[y];
  fst[y] = tot;
}
bool bfs() {
  memset(lev, -1, sizeof(lev));
  queue<int> q;
  while (!q.empty()) q.pop();
  q.push(s);
  lev[s] = 0;
  while (!q.empty()) {
    int x = q.front();
    q.pop();
    for (int i = fst[x]; ~i; i = nxt[i]) {
      int y = ver[i], c = cap[i];
      if (c && lev[y] < 0) lev[y] = lev[x] + 1, q.push(y);
    }
  }
  return lev[t] >= 0;
}
int dfs(int x, int lim) {
  if (x == t) return lim;
  int res = 0;
  for (int i = cur[x]; ~i; i = nxt[i]) {
    int y = ver[i], c = cap[i];
    if (c && lev[y] == lev[x] + 1) {
      int tmp = dfs(y, min(lim, c));
      if (!tmp) continue;
      lim -= tmp;
      res += tmp;
      cap[i] -= tmp;
      cap[i ^ 1] += tmp;
      if (!lim) {
        cur[x] = i;
        return res;
      }
    }
  }
  cur[x] = -1;
  return res;
}
int MF() {
  int ans = 0;
  while (bfs()) {
    memcpy(cur, fst, sizeof(cur));
    ans += dfs(s, INF);
  }
  return ans;
}
namespace seg {
int p[N << 2];
void build(int rt, int l, int r) {
  if (l == r) {
    p[rt] = l;
    return;
  }
  int mid = (l + r) >> 1;
  p[rt] = ++_;
  build(rt << 1, l, mid);
  build(rt << 1 | 1, mid + 1, r);
  addedge(p[rt], p[rt << 1], INF);
  addedge(p[rt], p[rt << 1 | 1], INF);
}
void link(int rt, int l, int r, int ql, int qr, int pv) {
  if (ql <= l && r <= qr) {
    addedge(pv, p[rt], 1);
    return;
  }
  int mid = (l + r) >> 1;
  if (ql <= mid) link(rt << 1, l, mid, ql, qr, pv);
  if (qr > mid) link(rt << 1 | 1, mid + 1, r, ql, qr, pv);
}
}  // namespace seg
struct node {
  int fl, a, b, c;
  node(int _fl = 0, int _a = 0, int _b = 0, int _c = 0) {
    fl = _fl;
    a = _a;
    b = _b;
    c = _c;
  }
} rr[N];
int anc, ans[N], ct[N];
void find(int x, int ff) {
  if (anc) return;
  if (x > n && x <= m + n) {
    anc = x - n;
    return;
  }
  for (int i = fst[x]; ~i; i = nxt[i]) {
    int y = ver[i], c = cap[i];
    if (y != ff && c) {
      cap[i]--;
      find(y, x);
      return;
    }
  }
}
int main() {
  m = read();
  n = read();
  _ = n + m;
  s = 0;
  t = ++_;
  tot = 1;
  memset(fst, -1, sizeof(fst));
  seg::build(1, 1, n);
  for (int i = 1; i <= m; i++) {
    int opt = read(), tmp = i + n;
    if (!opt) {
      addedge(s, tmp, 1);
      int k = read();
      while (k--) {
        int x = read();
        addedge(tmp, x, 1);
      }
    } else if (opt == 1) {
      addedge(s, tmp, 1);
      int l = read(), r = read();
      seg::link(1, 1, n, l, r, tmp);
    } else {
      addedge(s, tmp, 2);
      int a = read(), b = read(), c = read();
      addedge(tmp, a, 1);
      addedge(tmp, b, 1);
      addedge(tmp, c, 1);
      rr[i] = node(1, a, b, c);
    }
  }
  for (int i = 1; i <= n; i++) addedge(i, t, 1);
  cout << MF() << '\n';
  for (int i = fst[t]; ~i; i = nxt[i]) {
    if (cap[i]) {
      anc = 0;
      find(ver[i], t);
      ans[ver[i]] = anc;
      ct[anc]++;
    }
  }
  for (int i = 1; i <= m; i++) {
    if (rr[i].fl) {
      if (ct[i] == 1) {
        if (ans[rr[i].a] != i)
          ans[rr[i].a] = i;
        else
          ans[rr[i].b] = i;
      }
    }
  }
  for (int i = 1; i <= n; i++)
    if (ans[i]) cout << ans[i] << ' ' << i << '\n';
  return 0;
}
