#include <bits/stdc++.h>
using namespace std;
map<int, pair<int, int> > ans;
void dfs(int v, const int u, vector<char> &col,
         vector<pair<int, pair<int, int> > > &net, const int d);
int main(void) {
  int n = int(), p = int();
  scanf("%d%d", &n, &p);
  vector<char> col(n);
  vector<pair<int, pair<int, int> > > net(n, make_pair(-1, make_pair(-1, 0)));
  for (int i = 0; i < p; ++i) {
    int a = int(), b = int(), d = int();
    scanf("%d%d%d", &a, &b, &d);
    net[--b].first = --a;
    net[a].second.first = b;
    net[a].second.second = d;
  }
  vector<int> ind(n);
  for (int i = 0; i < n; ++i) ind[i] = i;
  random_shuffle(ind.begin(), ind.end());
  for (int u = 0; u < n; ++u)
    if (!col[ind[u]]) dfs(ind[u], ind[u], col, net, INT_MAX);
  printf("%d\n", ans.size());
  for (map<int, pair<int, int> >::iterator i = ans.begin(); i != ans.end(); ++i)
    printf("%d %d %d\n", i->first + 1, i->second.first + 1, i->second.second);
  return 0;
}
void dfs(int v, const int u, vector<char> &col,
         vector<pair<int, pair<int, int> > > &net, const int d) {
  if (net[v].second.first == -1) {
    if (u == v) return;
    ans[u] = make_pair(v, d);
    col[v] = 2;
    return;
  }
  col[v] = 1;
  switch (col[net[v].second.first]) {
    case 0:
      dfs(net[v].second.first, u, col, net, min(d, net[v].second.second));
      break;
    case 1:
      return;
    case 2:
      ans[u] = ans[net[v].second.first];
      ans[u].second = min(ans[u].second, min(d, net[v].second.second));
      ans.erase(net[v].second.first);
      break;
  }
  col[v] = 2;
}
