#include <bits/stdc++.h>
#pragma GCC optimize(3, "Ofast", "inline")
using namespace std;
int read() {
  int x = 0, f = 1;
  char ch = getchar();
  while (ch < '0' || ch > '9') {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9') {
    x = (x << 3) + (x << 1) + (ch ^ 48);
    ch = getchar();
  }
  return x * f;
}
struct node {
  int op, a, b, c;
} Q[5005];
int n, m, v[3000005], w[3000005], nxt[3000005], head[3000005],
    cnt = 1, cur[3000005], vis[3000005], dep[200005], S, T, Id[3000005], p,
    match[3000005];
void add(int a, int b, int c) {
  v[++cnt] = b;
  w[cnt] = c;
  nxt[cnt] = head[a];
  head[a] = cnt;
}
int dfs(int x, int limit) {
  if (x == T || !limit) return limit;
  int flow = 0, rlow = 0;
  for (int i = cur[x]; i != -1; i = nxt[i]) {
    cur[x] = i;
    if (dep[v[i]] == dep[x] + 1 && w[i]) {
      if ((rlow = dfs(v[i], min(w[i], limit)))) {
        flow += rlow;
        limit -= rlow;
        w[i] -= rlow;
        w[i ^ 1] += rlow;
        if (!limit) break;
      }
    }
  }
  return flow;
}
int bfs() {
  memset(dep, 0x3f, sizeof(dep));
  for (int i = S; i <= T; i++) cur[i] = head[i];
  queue<int> q;
  q.push(S);
  dep[S] = 0;
  while (!q.empty()) {
    int c = q.front();
    q.pop();
    vis[c] = 0;
    for (int i = head[c]; i != -1; i = nxt[i]) {
      if (dep[v[i]] > dep[c] + 1 && w[i]) {
        dep[v[i]] = dep[c] + 1;
        if (!vis[v[i]]) {
          vis[v[i]] = 1;
          q.push(v[i]);
        }
      }
    }
  }
  if (dep[T] == 0x3f3f3f3f) return 0;
  return 1;
}
int Dinic() {
  int maxflow = 0;
  while (bfs()) {
    maxflow += dfs(S, 0x3f3f3f3f);
  }
  return maxflow;
}
void build(int l, int r, int k) {
  if (l == r) {
    Id[k] = l + n;
    return;
  }
  int mid = (l + r) >> 1;
  Id[k] = ++p;
  build(l, mid, k * 2);
  build(mid + 1, r, k * 2 + 1);
  add(Id[k], Id[k * 2], 0x3f3f3f3f);
  add(Id[k * 2], Id[k], 0);
  add(Id[k], Id[k * 2 + 1], 0x3f3f3f3f);
  add(Id[k * 2 + 1], Id[k], 0);
}
void modify(int l, int r, int k, int x, int y, int val) {
  if (l >= x && r <= y) {
    add(val, Id[k], 1);
    add(Id[k], val, 0);
    return;
  }
  int mid = (l + r) >> 1;
  if (x <= mid) modify(l, mid, k * 2, x, y, val);
  if (y > mid) modify(mid + 1, r, k * 2 + 1, x, y, val);
}
void find_path(int x, int &ans, int fa) {
  if (ans) return;
  if (x >= 1 && x <= n) {
    ans = x;
    return;
  }
  for (int i = head[x]; i != -1; i = nxt[i]) {
    if (v[i] != fa && w[i]) {
      find_path(v[i], ans, x);
      w[i]--;
      return;
    }
  }
}
signed main() {
  memset(head, -1, sizeof(head));
  n = read();
  m = read();
  p = n + m;
  S = 0;
  build(1, m, 1);
  T = p + 1;
  for (int i = 1; i <= n; i++) {
    Q[i].op = read();
    if (Q[i].op == 0) {
      int siz = read();
      while (siz--) {
        int x = read();
        add(i, x + n, 1);
        add(x + n, i, 0);
      }
    }
    if (Q[i].op == 1) {
      int x = read(), y = read();
      modify(1, m, 1, x, y, i);
    }
    if (Q[i].op == 2) {
      Q[i].a = read();
      Q[i].b = read();
      Q[i].c = read();
      add(i, Q[i].a + n, 1);
      add(Q[i].a + n, i, 0);
      add(i, Q[i].b + n, 1);
      add(Q[i].b + n, i, 0);
      add(i, Q[i].c + n, 1);
      add(Q[i].c + n, i, 0);
    }
  }
  for (int i = 1; i <= n; i++) {
    if (Q[i].op != 2)
      add(S, i, 1), add(i, S, 0);
    else
      add(S, i, 2), add(i, S, 0);
  }
  for (int i = 1; i <= m; i++) add(i + n, T, 1), add(T, i + n, 0);
  int ans = Dinic();
  printf("%d\n", ans);
  for (int i = head[T]; i != -1; i = nxt[i]) {
    if (w[i]) {
      find_path(v[i], match[v[i]], T);
    }
  }
  for (int i = 1; i <= n; i++) {
    if (Q[i].op == 2) {
      int sum = 0;
      sum += (match[Q[i].a + n] == i);
      sum += (match[Q[i].b + n] == i);
      sum += (match[Q[i].c + n] == i);
      if (sum == 1) {
        if (match[Q[i].a + n] != i) {
          match[Q[i].a + n] = i;
          continue;
        }
        if (match[Q[i].b + n] != i) {
          match[Q[i].b + n] = i;
          continue;
        }
        if (match[Q[i].c + n] != i) {
          match[Q[i].c + n] = i;
          continue;
        }
      }
    }
  }
  for (int i = n + 1; i <= n + m; i++) {
    if (match[i]) printf("%d %d\n", match[i], i - n);
  }
}
