#include <bits/stdc++.h>
using namespace std;
const int M = (int)1e9 + 7;
const int N = (int)1e6 + 7;
int used[N];
vector<vector<pair<int, int> > > g(N);
vector<int> d, cur;
bool cycle = 0;
int tt = M;
void topsort(int v) {
  used[v] = 1;
  for (auto to : g[v]) {
    if (!used[to.first]) topsort(to.first);
  }
  d.push_back(v);
}
void dfs(int x) {
  used[x] = 1;
  for (auto to : g[x]) {
    if (used[to.first] == 1)
      cycle = 1;
    else if (used[to.first] == 0)
      dfs(to.first), tt = min(tt, to.second);
  }
  used[x] = 2;
  cur.push_back(x);
}
int main() {
  int n, p;
  cin >> n >> p;
  for (int i = 0; i < p; i++) {
    int u, v, len;
    cin >> u >> v >> len;
    g[u].push_back(make_pair(v, len));
  }
  for (int i = 1; i <= n; i++) {
    if (!used[i]) topsort(i);
  }
  for (int i = 1; i <= n; i++) used[i] = 0;
  vector<pair<int, pair<int, int> > > ans;
  reverse(d.begin(), d.end());
  for (auto x : d) {
    if (!used[x]) {
      cycle = 0;
      cur.clear();
      tt = M;
      dfs(x);
      if (!cycle && tt != M) {
        ans.push_back(make_pair(cur.back(), make_pair(cur.front(), tt)));
      }
    }
  }
  sort(ans.begin(), ans.end());
  cout << ans.size() << '\n';
  for (auto x : ans)
    cout << x.first << ' ' << x.second.first << ' ' << x.second.second << '\n';
  return 0;
}
