#include <bits/stdc++.h>
using namespace std;
inline int read() {
  int x = 0, f = 1, ch = getchar();
  while (ch < '0' || ch > '9') {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9') {
    x = x * 10 + ch - '0';
    ch = getchar();
  }
  return x * f;
}
inline void write(int x) {
  if (x < 0) putchar('-'), x = -x;
  if (x >= 10) write(x / 10);
  putchar(x % 10 + '0');
}
inline void writeln(int x) {
  write(x);
  puts("");
}
const int N = 1e5 + 5, INF = 1e5;
struct node {
  int son[2], mx;
} a[N * 30];
int rt[N], n, m, ans, tot;
int query(int k, int l, int r, int x) {
  if (!k || x < 0) return 0;
  if (l == r) return a[k].mx;
  int mid = (l + r) >> 1;
  if (mid >= x)
    return query(a[k].son[0], l, mid, x);
  else
    return max(a[a[k].son[0]].mx, query(a[k].son[1], mid + 1, r, x));
}
void update(int &k, int l, int r, int x, int w) {
  if (!k) k = ++tot;
  a[k].mx = max(a[k].mx, w);
  if (l == r) return;
  int mid = (l + r) >> 1;
  if (mid >= x)
    update(a[k].son[0], l, mid, x, w);
  else
    update(a[k].son[1], mid + 1, r, x, w);
}
int main() {
  n = read();
  m = read();
  for (int i = 1; i <= m; i++) {
    int u = read(), v = read(), w = read();
    int tmp = query(rt[u], 0, INF, w - 1) + 1;
    update(rt[v], 0, INF, w, tmp);
    ans = max(ans, tmp);
  }
  writeln(ans);
  return 0;
}
