#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 5010;
int _w;
int n, m;
namespace Dinic {
const int V = 20000;
const int E = 2000000;
struct Edge {
  int u, v, c, f;
  Edge() {}
  Edge(int u, int v, int c, int f) : u(u), v(v), c(c), f(f) {}
};
int n, m, s, t;
int head[V], nxt[E * 2];
Edge edge[E * 2];
void init(int _n) {
  n = _n, m = 0;
  memset(head, -1, sizeof head);
}
int link(int u, int v, int c) {
  int rtn = m;
  edge[m] = Edge(u, v, c, 0);
  nxt[m] = head[u], head[u] = m++;
  edge[m] = Edge(v, u, 0, 0);
  nxt[m] = head[v], head[v] = m++;
  return rtn;
}
int dis[V], cur[V], q[V], begin, end;
bool bfs() {
  for (int i = 0; i < n; ++i) dis[i] = INF;
  dis[s] = 0, begin = end = 0;
  q[end++] = s;
  while (begin != end) {
    int u = q[begin++];
    for (int i = head[u]; ~i; i = nxt[i]) {
      Edge &e = edge[i];
      if (e.c > e.f && dis[e.v] == INF) {
        dis[e.v] = dis[u] + 1;
        q[end++] = e.v;
      }
    }
  }
  return dis[t] != INF;
}
int dfs(int u, int res) {
  if (u == t || !res) return res;
  int flow = 0;
  for (int &i = cur[u]; ~i; i = nxt[i]) {
    Edge &e = edge[i];
    if (e.c > e.f && dis[e.v] == dis[u] + 1) {
      int f = dfs(e.v, min(e.c - e.f, res));
      flow += f, res -= f;
      e.f += f, edge[i ^ 1].f -= f;
      if (!res) break;
    }
  }
  return flow;
}
int solve(int _s, int _t) {
  s = _s, t = _t;
  int flow = 0;
  while (bfs()) {
    for (int i = 0; i < n; ++i) cur[i] = head[i];
    flow += dfs(s, INF);
  }
  return flow;
}
void clear_flow() {
  for (int i = 0; i < m; ++i) edge[i].f = 0;
}
}  // namespace Dinic
int nid, s, t, id[N];
namespace SGT {
int id[N * 4], ql, qr, qv, mid[N], eid[N];
void _init(int o, int L, int R) {
  id[o] = nid++;
  if (L == R) {
    mid[L] = id[o];
    return;
  }
  int M = (L + R) / 2, lc = o << 1, rc = lc | 1;
  _init(lc, L, M), _init(rc, M + 1, R);
}
void init() { _init(1, 1, m); }
void _build(int o, int L, int R) {
  if (L == R) {
    eid[L] = Dinic::link(id[o], t, 1);
  } else {
    int M = (L + R) / 2, lc = o << 1, rc = lc | 1;
    Dinic::link(id[o], id[lc], INF);
    Dinic::link(id[o], id[rc], INF);
    _build(lc, L, M), _build(rc, M + 1, R);
  }
}
void build() { _build(1, 1, m); }
void _connect(int o, int L, int R) {
  if (L >= ql && R <= qr) {
    Dinic::link(qv, id[o], INF);
  } else {
    int M = (L + R) / 2, lc = o << 1, rc = lc | 1;
    if (ql <= M) _connect(lc, L, M);
    if (qr > M) _connect(rc, M + 1, R);
  }
}
void connect(int u, int l, int r) {
  ql = l, qr = r, qv = u;
  _connect(1, 1, m);
}
}  // namespace SGT
int type[N], l[N], r[N], a[N], b[N], c[N], ea[N], eb[N], ec[N], anscnt;
vector<pair<int, int> > con[N], ans;
set<int> beat;
void prelude() {
  using Dinic::edge;
  using SGT::eid;
  for (int i = 1; i <= m; ++i) {
    int e = eid[i];
    if (edge[e].f) beat.insert(i);
  }
}
void solve2() {
  using Dinic::edge;
  using SGT::eid;
  for (int i = 1; i <= n; ++i)
    if (type[i] == 2) {
      int cnt = 0;
      if (edge[ea[i]].f) {
        ++cnt;
        beat.erase(a[i]);
        ans.push_back(pair<int, int>(i, a[i]));
      }
      if (edge[eb[i]].f) {
        ++cnt;
        beat.erase(b[i]);
        ans.push_back(pair<int, int>(i, b[i]));
      }
      if (edge[ec[i]].f) {
        ++cnt;
        beat.erase(c[i]);
        ans.push_back(pair<int, int>(i, c[i]));
      }
      if (cnt == 1 && beat.count(a[i])) {
        ++cnt;
        beat.erase(a[i]);
        ans.push_back(pair<int, int>(i, a[i]));
      }
      if (cnt == 1 && beat.count(b[i])) {
        ++cnt;
        beat.erase(b[i]);
        ans.push_back(pair<int, int>(i, b[i]));
      }
      if (cnt == 1 && beat.count(c[i])) {
        ++cnt;
        beat.erase(c[i]);
        ans.push_back(pair<int, int>(i, c[i]));
      }
    }
}
void solve0() {
  using Dinic::edge;
  for (int i = 1; i <= n; ++i)
    if (type[i] == 0) {
      int k = (int)con[i].size();
      for (int j = 0; j < k; ++j) {
        int nod = con[i][j].first;
        int eid = con[i][j].second;
        if (edge[eid].f && beat.count(nod)) {
          beat.erase(nod);
          ans.push_back(pair<int, int>(i, nod));
        }
      }
    }
}
struct Segment {
  int u, l, r;
  Segment() {}
  Segment(int u, int l, int r) : u(u), l(l), r(r) {}
  bool operator<(const Segment &rhs) const {
    if (l == rhs.l)
      return r < rhs.r;
    else
      return l < rhs.l;
  }
};
Segment seg[N];
int segn, vis[N];
void solve1() {
  for (int i = 1; i <= n; ++i)
    if (type[i] == 1) seg[segn++] = Segment(i, l[i], r[i]);
  while (!beat.empty()) {
    int v = *beat.begin();
    beat.erase(v);
    int minr = INF;
    for (int i = 0; i < segn; ++i) {
      if (vis[i]) continue;
      int l = seg[i].l;
      int r = seg[i].r;
      if (l <= v && v <= r) minr = min(minr, r);
    }
    for (int i = 0; i < segn; ++i) {
      if (vis[i]) continue;
      int u = seg[i].u;
      int l = seg[i].l;
      int r = seg[i].r;
      if (l <= v && v <= r && r == minr) {
        vis[i] = 1;
        ans.push_back(pair<int, int>(u, v));
        break;
      }
    }
  }
}
void solve() {
  prelude();
  solve2();
  solve0();
  solve1();
  int cnt = (int)ans.size();
  assert(cnt == anscnt);
  printf("%d\n", cnt);
  for (int i = 0; i < cnt; ++i) printf("%d %d\n", ans[i].first, ans[i].second);
}
int main() {
  _w = scanf("%d%d", &n, &m);
  SGT::init();
  for (int i = 1; i <= n; ++i) id[i] = nid++;
  s = nid++, t = nid++;
  Dinic::init(nid);
  SGT::build();
  for (int i = 1; i <= n; ++i) {
    _w = scanf("%d", &type[i]);
    if (type[i] == 0) {
      Dinic::link(s, id[i], 1);
      int k;
      _w = scanf("%d", &k);
      for (int j = 0; j < k; ++j) {
        int tmp, eid;
        _w = scanf("%d", &tmp);
        eid = Dinic::link(id[i], SGT::mid[tmp], 1);
        con[i].push_back(pair<int, int>(tmp, eid));
      }
    } else if (type[i] == 1) {
      Dinic::link(s, id[i], 1);
      _w = scanf("%d%d", l + i, r + i);
      SGT::connect(id[i], l[i], r[i]);
    } else {
      Dinic::link(s, id[i], 2);
      _w = scanf("%d%d%d", a + i, b + i, c + i);
      ea[i] = Dinic::link(id[i], SGT::mid[a[i]], 1);
      eb[i] = Dinic::link(id[i], SGT::mid[b[i]], 1);
      ec[i] = Dinic::link(id[i], SGT::mid[c[i]], 1);
    }
  }
  anscnt = Dinic::solve(s, t);
  solve();
  return 0;
}
