#include <bits/stdc++.h>
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
using namespace std;
long long gcd(long long a, long long b) { return (a == 0) ? b : gcd(b % a, a); }
long long cnt1(long long x) {
  long long cnt = 0;
  while (x > 0) x &= x - 1, cnt++;
  return cnt;
}
long long fact(long long n) { return n == 0 ? 1LL : n * fact(n - 1); }
long long fact(long long n, long long p) {
  return n == 0 ? 1LL : n * fact(n - 1) % p;
}
long long cnk(long long n, long long k) {
  return n == 1 || k == 1 ? 1 : cnk(n - 1, k) + cnk(n - 1, k - 1);
}
long long pow(long long a, long long n, long long p) {
  if (n == 0) return 1;
  long long t = pow(a, n / 2, p);
  return t * t % p * (n % 2 ? a : 1) % p;
}
long long back(long long x, long long p) { return pow(x, p - 2, p); }
long long cnk(long long n, long long k, long long p) {
  return fact(n, p) * back(fact(k, p), p) % p * back(fact(n - k, p), p) % p;
}
template <class T>
istream &operator>>(istream &stream, vector<T> &v) {
  for (long long i = 0; i < (long long)v.size(); i++) stream >> v[i];
  return stream;
}
template <class T>
ostream &operator<<(ostream &stream, vector<T> v) {
  for (long long i = 0; i < (long long)v.size(); i++) stream << v[i] << ' ';
  stream << '\n';
  return stream;
}
template <class A, class B>
istream &operator>>(istream &stream, pair<A, B> &p) {
  return stream >> p.first >> p.second;
}
struct Node {
  Node *l = 0, *r = 0;
  long long s = 0;
};
inline Node *get_ch(Node *v) {
  if (v == 0)
    return new Node;
  else
    return v;
}
inline void get(Node *&v) {
  v->l = get_ch(v->l);
  v->r = get_ch(v->r);
}
void update(Node *v, long long l, long long r, long long pos, long long x) {
  if (r - l == 1)
    v->s = x;
  else {
    long long m = (r + l) >> 1;
    get(v);
    if (pos < m)
      update(v->l, l, m, pos, x);
    else
      update(v->r, m, r, pos, x);
    v->s = v->l->s + v->r->s;
  }
}
long long find(Node *a, Node *b, long long l, long long r) {
  if (r - l == 1)
    return l;
  else {
    long long m = (r + l) >> 1;
    get(a);
    get(b);
    if (a->l->s > b->l->s)
      return find(a->l, b->l, l, m);
    else
      return find(a->r, b->r, m, r);
  }
}
signed main() {
  srand(time(0));
  ios_base::sync_with_stdio(0), cin.tie(0);
  long long n, m;
  cin >> n >> m;
  vector<Node *> t(n);
  for (long long i = 0; i < n; i++) t[i] = new Node;
  set<pair<long long, long long>> sz;
  long long sum = 0;
  for (long long i = 0; i < n; i++) {
    long long x;
    cin >> x;
    for (long long j = 0; j < x; j++) {
      long long pos;
      cin >> pos;
      pos--;
      update(t[i], 0, m, pos, 1);
    }
    sz.insert({x, i});
    sum += x;
  }
  vector<vector<long long>> ans;
  long long need = sum / n;
  while (sz.begin()->first < need || sz.rbegin()->first > need + 1) {
    long long v = sz.begin()->second, u = sz.rbegin()->second;
    long long x = sz.begin()->first, y = sz.rbegin()->first;
    sz.erase(sz.begin());
    sz.erase(prev(sz.end()));
    sz.insert({x + 1, v});
    sz.insert({y - 1, u});
    long long pos = find(t[u], t[v], 0, m);
    update(t[u], 0, m, pos, 0);
    update(t[v], 0, m, pos, 1);
    ans.push_back({u + 1, v + 1, pos + 1});
  }
  cout << ans.size() << '\n';
  for (long long i = 0; i < ans.size(); i++) cout << ans[i];
}
