#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const double eps = 1e-8;
const double PI = acos(-1.0);
const int MAXN = 2e5 + 5;
const int MAXM = 2e6 + 5;
const int MOD = 1e9 + 7;
int sgn(double x) {
  if (fabs(x) < eps) return 0;
  if (x < 0)
    return -1;
  else
    return 1;
}
long long pw(long long a, long long n, long long mod) {
  long long ret = 1;
  while (n) {
    if (n & 1) ret = ret * a % mod;
    a = a * a % mod;
    n >>= 1;
  }
  return ret;
}
long long gcd(long long a, long long b) { return b == 0 ? a : gcd(b, a % b); }
long long lcm(long long a, long long b) { return a / gcd(a, b) * b; }
void inc(long long &a, long long b) {
  a += b;
  if (a >= MOD) a -= MOD;
}
void dec(long long &a, long long b) {
  a -= b;
  if (a < 0) a += MOD;
}
int mul(int a, int b) {
  long long c = 1ll * a * b;
  return c - c / MOD * MOD;
}
int n, m, tot, head[MAXN];
struct Edge {
  int to, w, nxt;
} edge[MAXM];
void init() {
  tot = 0;
  memset(head, -1, sizeof(head));
}
void addedge(int u, int v, int w) {
  edge[tot].to = v;
  edge[tot].w = w;
  edge[tot].nxt = head[u];
  head[u] = tot++;
  edge[tot].to = u;
  edge[tot].w = 0;
  edge[tot].nxt = head[v];
  head[v] = tot++;
}
int st, ed, d[MAXN], cur[MAXN];
int bfs() {
  queue<int> Q;
  for (int i = st; i < ed + 1; i++) d[i] = 0;
  Q.push(st);
  d[st] = 1;
  while (!Q.empty()) {
    int x = Q.front();
    Q.pop();
    for (int i = head[x]; i != -1; i = edge[i].nxt) {
      int v = edge[i].to;
      if (!d[v] && edge[i].w) {
        d[v] = d[x] + 1;
        Q.push(v);
      }
    }
  }
  return d[ed];
}
int dfs(int x, int w) {
  if (x == ed || w == 0) return w;
  int f, ret = 0;
  for (int &i = cur[x]; i != -1; i = edge[i].nxt) {
    int v = edge[i].to;
    if (d[v] == d[x] + 1 && (f = dfs(v, min(w, edge[i].w)))) {
      edge[i].w -= f;
      edge[i ^ 1].w += f;
      ret += f;
      w -= f;
      if (!w) break;
    }
  }
  return ret;
}
int Dinic() {
  int flow = 0;
  while (bfs()) {
    for (int i = st; i < ed + 1; i++) cur[i] = head[i];
    flow += dfs(st, INF);
  }
  return flow;
}
int sz, id[MAXN << 2];
void build(int l, int r, int rt) {
  if (l == r) {
    id[rt] = l;
    return;
  }
  id[rt] = ++sz;
  int mid = l + r >> 1;
  build(l, mid, rt << 1);
  build(mid + 1, r, rt << 1 | 1);
  addedge(id[rt], id[rt << 1], INF);
  addedge(id[rt], id[rt << 1 | 1], INF);
}
void upd(int i, int L, int R, int l, int r, int rt) {
  if (L <= l && r <= R) {
    addedge(sz + i, id[rt], 1);
    return;
  }
  int mid = l + r >> 1;
  if (L <= mid) upd(i, L, R, l, mid, rt << 1);
  if (R > mid) upd(i, L, R, mid + 1, r, rt << 1 | 1);
}
int res, barn[MAXN];
void find(int u, int weap) {
  if (u == ed) return;
  for (int i = head[u]; i != -1; i = edge[i].nxt) {
    int v = edge[i].to;
    if (!(i & 1) && edge[i ^ 1].w && res) {
      find(v, weap);
      edge[i].w++;
      edge[i ^ 1].w--;
      if (v == ed) {
        barn[u] = weap;
        res--;
      }
    }
  }
}
int A[MAXN], B[MAXN], C[MAXN], sum[MAXN];
int main() {
  scanf("%d%d", &n, &m);
  init();
  sz = m;
  build(1, m, 1);
  st = 0, ed = sz + n + 1;
  int ty, k, x, l, r;
  for (int i = 1; i < n + 1; i++) {
    scanf("%d", &ty);
    if (ty == 0) {
      scanf("%d", &k);
      for (int j = 0; j < k; j++) scanf("%d", &x), addedge(sz + i, x, 1);
    } else if (ty == 1) {
      scanf("%d%d", &l, &r), upd(i, l, r, 1, m, 1);
    } else {
      scanf("%d%d%d", &A[i], &B[i], &C[i]);
      addedge(sz + i, A[i], 1);
      addedge(sz + i, B[i], 1);
      addedge(sz + i, C[i], 1);
    }
  }
  for (int i = 1; i < n + 1; i++) addedge(st, sz + i, A[i] ? 2 : 1);
  for (int i = 1; i < m + 1; i++) addedge(i, ed, 1);
  printf("%d\n", Dinic());
  for (int i = head[st]; i != -1; i = edge[i].nxt) {
    int v = edge[i].to;
    if (edge[i ^ 1].w) res = edge[i ^ 1].w, find(v, v - sz);
  }
  for (int i = 1; i < m + 1; i++) sum[barn[i]]++;
  for (int i = 1; i < n + 1; i++) {
    if (A[i] && sum[i] == 1) {
      if (barn[A[i]] && barn[A[i]] != i)
        barn[A[i]] = i;
      else if (barn[B[i]] && barn[B[i]] != i)
        barn[B[i]] = i;
      else
        barn[C[i]] = i;
    }
  }
  for (int i = 1; i < m + 1; i++)
    if (barn[i]) printf("%d %d\n", barn[i], i);
}
