#include <bits/stdc++.h>
#pragma GCC optimize("O3", "unroll-loops")
using namespace std;
template <class T>
inline void sort(T &a) {
  sort((a).begin(), (a).end());
}
template <class T>
inline void rsort(T &a) {
  sort((a).rbegin(), (a).rend());
}
template <class T>
inline void reverse(T &a) {
  reverse((a).begin(), (a).end());
}
template <class T, class U>
inline void checkmin(T &x, U y) {
  if (x > y) x = y;
}
template <class T, class U>
inline void checkmax(T &x, U y) {
  if (x < y) x = y;
}
struct bag : public set<int> {
  int ind;
};
bool cmp(const bag &a, const bag &b) { return int(a.size()) > int(b.size()); }
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  cout << fixed << setprecision(20);
  srand(time(nullptr));
  int n, m;
  cin >> n >> m;
  vector<bag> arr(n);
  int sumb = 0;
  for (int i = 0; i < n; ++i) {
    int c;
    cin >> c;
    sumb += c;
    for (int j = 0; j < c; ++j) {
      int k;
      cin >> k;
      arr[i].insert(k);
    }
    arr[i].ind = i;
  }
  sort((arr).begin(), (arr).end(), cmp);
  vector<int> first(n);
  for (int i = 0; i < n; ++i) first[i] = sumb / n + (sumb % n > i);
  int ptra = 0, ptrb = n - 1;
  vector<vector<int>> ans;
  while (ptra<ptrb &&int(arr[ptra].size())> first[ptra]) {
    int x = *(arr[ptra].begin());
    while (int(arr[ptra].size()) > first[ptra] &&
           int(arr[ptrb].size()) < first[ptrb]) {
      if (!arr[ptrb].count(x)) {
        arr[ptra].erase(x);
        arr[ptrb].insert(x);
        ans.push_back({arr[ptra].ind, arr[ptrb].ind, x});
      }
      auto it = arr[ptra].upper_bound(x);
      if (it == arr[ptra].end()) break;
      x = *it;
    }
    if (int(arr[ptra].size()) == first[ptra]) ++ptra;
    if (int(arr[ptrb].size()) == first[ptrb]) --ptrb;
  }
  cout << int(ans.size()) << '\n';
  for (auto i : ans) cout << i[0] + 1 << ' ' << i[1] + 1 << ' ' << i[2] << '\n';
  return 0;
}
