#include <bits/stdc++.h>
using namespace std;
map<int, int> pos;
struct DINIC {
  static const int maxn = 15005, inf = 0x3f3f3f3f;
  struct edge {
    int u, v, c, rev;
    edge(int _u, int _v, int _c) : u(_u), v(_v), c(_c), rev(0) {}
    int go(int i) { return u ^ v ^ i; }
    int cap(int i) { return i == u ? c : rev; }
    void flow(int i, int f) {
      if (i == v) f *= -1;
      c -= f, rev += f;
    }
  };
  vector<edge> e;
  vector<int> g[maxn];
  int d[maxn], it[maxn], n, s, t;
  void init(int _n, int _s, int _t) { n = _n, s = _s, t = _t; }
  void link(int x, int y, int c = inf) {
    g[x].push_back(e.size()), g[y].push_back(e.size()), e.emplace_back(x, y, c);
  }
  bool bfs() {
    memset(d, inf, sizeof(d));
    queue<int> q;
    d[s] = 0, q.push(s);
    while (!q.empty()) {
      int i = q.front();
      q.pop();
      for (int j : g[i])
        if (e[j].cap(i) && d[e[j].go(i)] == inf)
          d[e[j].go(i)] = d[i] + 1, q.push(e[j].go(i));
    }
    return d[t] != inf;
  }
  int dfs(int i, int f) {
    if (i == t) return f;
    for (int &ii = it[i]; ii < g[i].size(); ++ii) {
      edge &j = e[g[i][ii]];
      if (j.cap(i) && d[j.go(i)] == d[i] + 1) {
        int ret = dfs(j.go(i), min(f, j.cap(i)));
        if (ret) return j.flow(i, ret), ret;
      }
    }
    return 0;
  }
  int flow() {
    int ans = 0;
    while (bfs()) {
      memset(it, 0, sizeof(it));
      int ret;
      while (ret = dfs(s, inf)) ans += ret;
    }
    return ans;
  }
  vector<vector<int>> track(int _n) {
    vector<vector<int>> v(n);
    for (int i = n - 1; i > 1; --i)
      for (int j : g[i])
        if (e[j].rev && i == e[j].u) {
          if (e[j].v == t)
            v[i].push_back(pos[i]);
          else
            for (int ii = 0; ii < e[j].rev; ++ii)
              v[i].push_back(v[e[j].v].back()), v[e[j].v].pop_back();
        }
    return vector<vector<int>>(v.begin() + 2, v.begin() + 2 + _n);
  }
} flow;
int _id;
struct seg {
  int l, r, v;
  seg *ch[2]{};
  seg(int _l, int _r) : l(_l), r(_r) {
    v = _id++;
    if (l < r - 1) {
      ch[0] = new seg(l, l + r >> 1), ch[1] = new seg(l + r >> 1, r);
      flow.link(v, ch[0]->v), flow.link(v, ch[1]->v);
    } else
      flow.link(v, 1, 1), pos[v] = l;
  }
  void link(int _l, int _r, int i) {
    if (_l <= l && r <= _r) {
      flow.link(i, v, 1);
      return;
    }
    int m = l + r >> 1;
    if (_l < m) ch[0]->link(_l, _r, i);
    if (m < _r) ch[1]->link(_l, _r, i);
  }
};
int main() {
  ios::sync_with_stdio(0), cin.tie(0);
  int n, m, s = _id++, t = _id++;
  cin >> n >> m;
  int id[n];
  for (int &i : id) i = _id++;
  seg rt(0, m);
  flow.init(_id, s, t);
  vector<array<int, 4>> v3;
  for (int i = 0; i < n; ++i) {
    int ty;
    cin >> ty;
    if (ty == 0) {
      int sz;
      cin >> sz;
      while (sz--) {
        int x;
        cin >> x;
        rt.link(x - 1, x, id[i]);
      }
      flow.link(s, id[i], 1);
    } else if (ty == 1) {
      int x, y;
      cin >> x >> y;
      rt.link(x - 1, y, id[i]);
      flow.link(s, id[i], 1);
    } else {
      int x, y, z;
      cin >> x >> y >> z;
      --x, --y, --z;
      v3.push_back({i, x, y, z});
      rt.link(x, x + 1, id[i]), rt.link(y, y + 1, id[i]),
          rt.link(z, z + 1, id[i]);
      flow.link(s, id[i], 2);
    }
  }
  cout << flow.flow() << '\n';
  vector<vector<int>> ans = flow.track(n);
  vector<int> v(m, -1);
  for (auto i : v3)
    if (ans[i[0]].size() == 1) v[ans[i[0]][0] == i[1] ? i[2] : i[1]] = i[0];
  for (int i = 0; i < n; ++i)
    for (int j : ans[i]) {
      cout << (v[j] == -1 ? i + 1 : v[j] + 1) << ' ' << j + 1 << '\n';
    }
}
