#include <bits/stdc++.h>
using namespace std;
const long long N = 1e5 + 5, MX = 2e5, MN = 0;
struct node;
extern node* empty;
struct node {
  int mx;
  node *LF, *RT;
  node() : mx(0), LF(this), RT(this) {}
  node(int val, node* lf = empty, node* rt = empty) : mx(val), LF(lf), RT(rt) {}
};
node* empty = new node();
node* insert(int val, int ind, node* cur, int ns = 0, int ne = MX) {
  if (ind > ne or ind < ns) return cur;
  if (ns == ne) return new node(val);
  int mid = ns + (ne - ns) / 2;
  node* lf = insert(val, ind, cur->LF, ns, mid);
  node* rt = insert(val, ind, cur->RT, mid + 1, ne);
  return new node(max(lf->mx, rt->mx), lf, rt);
}
int getMax(int qe, node* cur, int ns = 0, int ne = MX) {
  if (qe < 0) return 0;
  if (ns > qe) return 0;
  if (ne <= qe) return cur->mx;
  int mid = ns + (ne - ns) / 2;
  return max(getMax(qe, cur->LF, ns, mid), getMax(qe, cur->RT, mid + 1, ne));
}
node* roots[N];
int main() {
  int n, m;
  scanf("%d%d", &n, &m);
  for (long long i = 1; i <= n; i++) {
    roots[i] = empty;
  }
  for (long long i = 0; i < m; i++) {
    int a, b, w;
    scanf("%d%d%d", &a, &b, &w);
    roots[b] = insert(getMax(w - 1, roots[a]) + 1, w, roots[b]);
  }
  int ans = 0;
  for (long long i = 1; i <= n; i++) {
    ans = max(ans, getMax(MX, roots[i]));
  }
  printf("%d\n", ans);
  return 0;
}
