#include <bits/stdc++.h>
using namespace std;
const int MN = 1e5 + 5;
struct qry {
  int t;
  unordered_set<int> s;
} inp[MN];
struct cmp {
  bool operator()(const qry *lhs, const qry *rhs) {
    return pair<int, int>(lhs->s.size(), lhs->t) <
           pair<int, int>(rhs->s.size(), rhs->t);
  }
};
int N, M, lav, hav, tot = 0;
set<qry *, cmp> presents;
vector<pair<pair<int, int>, int> > ops;
bool ins(qry *x) {
  presents.insert(x);
  return x->s.size() < lav || x->s.size() > hav;
}
void exchange(qry *l, qry *h) {
  auto &ls = l->s, &hs = h->s;
  int mops = max(1, (int)min(lav - ls.size(), hs.size() - hav));
  for (auto it = hs.begin(); mops > 0;) {
    assert(it != hs.end());
    int x = *it;
    if (ls.insert(x).second) {
      it = hs.erase(it);
      mops--;
      ops.push_back({{h->t, l->t}, x});
    } else {
      it++;
    }
  }
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cin >> N >> M;
  for (int i = 0, v, x; i < N; i++) {
    inp[i].t = i + 1;
    cin >> v;
    tot += v;
    while (v--) {
      cin >> x;
      inp[i].s.insert(x);
    }
  }
  lav = tot / N;
  hav = lav + (tot % N > 0);
  for (int i = 0; i < N; i++) {
    ins(&inp[i]);
  }
  while (!presents.empty()) {
    qry *l = *presents.begin(), *h = *presents.rbegin();
    if ((l->s.size() >= lav) && (h->s.size() <= hav)) break;
    presents.erase(l);
    presents.erase(h);
    exchange(l, h);
    assert(!ins(l) | !ins(h));
  }
  printf("%d\n", ops.size());
  for (auto p : ops) {
    printf("%d %d %d\n", p.first.first, p.first.second, p.second);
  }
  return 0;
}
