#include <bits/stdc++.h>
using namespace std;
const long long MAX = 3e5 + 7;
long long dp[MAX];
struct edge {
  long long from, to;
  long long val;
} e[MAX << 1];
long long eid = 0, head[MAX];
inline void adde(long long x, long long y, long long w) {
  e[++eid].from = x;
  e[eid].to = y;
  e[eid].val = w;
}
bool cmp(edge a, edge b) { return a.val < b.val; }
long long tmp[MAX];
long long read() {
  long long num = 0, bj = 1;
  char ch = getchar();
  while (!isdigit(ch)) {
    if (ch == '-') {
      bj = -1;
    }
    ch = getchar();
  }
  while (isdigit(ch)) {
    num = num * 10 + ch - '0';
    ch = getchar();
  }
  return bj * num;
}
long long upd[MAX], tot = 0;
signed main() {
  long long N, M;
  cin >> N >> M;
  for (register long long i = 1; i <= M; i++) {
    long long fr, to, val;
    fr = read();
    to = read();
    val = read();
    adde(fr, to, val);
  }
  sort(e + 1, e + 1 + M, cmp);
  for (register long long i = 1; i <= M; i++) {
    tot = 0;
    while (e[i].val == e[i + 1].val) {
      upd[++tot] = i;
      i++;
    }
    upd[++tot] = i;
    for (register long long j = 1; j <= tot; j++) {
      long long u = e[upd[j]].from, v = e[upd[j]].to;
      tmp[u] = dp[u];
      tmp[v] = dp[v];
    }
    for (register long long j = 1; j <= tot; j++) {
      long long u = e[upd[j]].from, v = e[upd[j]].to;
      dp[v] = max(dp[v], tmp[u] + 1);
    }
    for (register long long j = 1; j <= tot; j++) {
      tmp[e[upd[j]].from] = tmp[e[upd[j]].to] = 0;
    }
  }
  long long maxx = -1;
  for (register long long i = 1; i <= N; i++) {
    maxx = max(maxx, dp[i]);
  }
  cout << maxx << endl;
}
