#include <bits/stdc++.h>
using namespace std;
struct Box {
  struct Node {
    Node *l, *r;
    int cnt;
    Node() : l(0), r(0), cnt(0) {}
  };
  Node *root;
  Box *prev, *next;
  int id;
  Box(int _id = -1) : id(_id), root(0), prev(this), next(this) {}
};
vector<Box::Node *> freeNodes;
Box::Node *new_node() {
  Box::Node *n;
  if (!freeNodes.empty()) {
    n = freeNodes.back();
    freeNodes.pop_back();
    new (n) Box::Node();
  } else {
    n = new Box::Node;
  }
  return n;
}
void delete_node(Box::Node *n) { freeNodes.push_back(n); }
void print_node(Box::Node *n, int mn, int mx) {
  int mid = (mn + mx) / 2;
  if (n && n->cnt) {
    if (mn + 1 == mx) {
      printf("%d ", mn + 1);
      return;
    }
    print_node(n->l, mn, mid);
    print_node(n->r, mid, mx);
  }
}
void insert_item(Box::Node *wh, int mn, int mx, int it) {
  wh->cnt++;
  if (mn + 1 == mx) {
    return;
  }
  Box::Node **nwh;
  int nmn, nmx;
  int mid = (mn + mx) / 2;
  if (it < mid) {
    nmn = mn;
    nmx = mid;
    nwh = &wh->l;
  } else {
    nmn = mid;
    nmx = mx;
    nwh = &wh->r;
  }
  if (!*nwh) {
    *nwh = new Box::Node;
  }
  insert_item(*nwh, nmn, nmx, it);
}
int move_item(Box::Node *from, Box::Node *to, int mn, int mx) {
  if (mn + 1 == mx) {
    to->cnt++;
    from->cnt--;
    return mn;
  }
  int item;
  int nmn, nmx;
  Box::Node **nfrom, **nto;
  if (from->l && (!to->l || from->l->cnt > to->l->cnt)) {
    nmn = mn;
    nmx = (mn + mx) / 2;
    nfrom = &from->l;
    nto = &to->l;
  } else {
    nmn = (mn + mx) / 2;
    nmx = mx;
    nfrom = &from->r;
    nto = &to->r;
  }
  if (!*nto) {
    *nto = new_node();
  }
  item = move_item(*nfrom, *nto, nmn, nmx);
  if (!(*nfrom)->cnt) {
    delete_node(*nfrom);
    *nfrom = 0;
  }
  to->cnt++;
  from->cnt--;
  return item;
}
int n, m;
Box boxes[100005];
int minBox = INT_MAX, maxBox = INT_MIN;
int move_item(Box *from, Box *to) {
  if (!to->root) {
    to->root = new_node();
  }
  auto it = move_item(from->root, to->root, 0, m);
  if (!from->root->cnt) {
    delete_node(from->root);
  }
  return it;
}
void insert_item(Box *bx, int it) {
  if (!bx->root) {
    bx->root = new_node();
  }
  insert_item(bx->root, 0, m, it);
}
void remove_box(Box *nbox) {
  nbox->prev->next = nbox->next;
  nbox->next->prev = nbox->prev;
}
void move_box(Box *nbox, Box *head) {
  nbox->prev->next = nbox->next;
  nbox->next->prev = nbox->prev;
  nbox->next = head->next;
  nbox->prev = head;
  head->next = nbox;
  nbox->next->prev = nbox;
}
void print_box(Box *b) { print_node(b->root, 0, m); }
Box *create_box(int s, int i) {
  auto head = &boxes[s];
  auto nbox = new Box(i);
  move_box(nbox, head);
  return nbox;
}
struct Move {
  int f, t, k;
};
vector<Move> moves;
int main() {
  int n;
  FILE *f = stdin;
  fscanf(f, " %d %d", &n, &m);
  for (int i = (0); i < (n); ++i) {
    int s;
    fscanf(f, " %d", &s);
    Box *b = create_box(s, i);
    minBox = min(minBox, s);
    maxBox = max(maxBox, s);
    for (int j = (0); j < (s); ++j) {
      int p;
      fscanf(f, " %d", &p);
      --p;
      insert_item(b, p);
    }
  }
  while (minBox + 1 < maxBox) {
    auto from = boxes[maxBox].next;
    auto to = boxes[minBox].next;
    int it = move_item(from, to);
    Move mm;
    mm.f = from->id + 1;
    mm.t = to->id + 1;
    mm.k = it + 1;
    moves.push_back(mm);
    move_box(from, &boxes[maxBox - 1]);
    move_box(to, &boxes[minBox + 1]);
    while (boxes[maxBox].prev == &boxes[maxBox]) {
      --maxBox;
    }
    while (boxes[minBox].prev == &boxes[minBox]) {
      ++minBox;
    }
  }
  printf("%d\n", (int)moves.size());
  for (auto &m : moves) {
    printf("%d %d %d\n", m.f, m.t, m.k);
  }
  return 0;
}
