#include <bits/stdc++.h>
using namespace std;
template <class T>
bool cmax(T& a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <class T>
bool cmin(T& a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
const int INF = 1e9;
const int N = 1e5 + 10;
template <class T>
struct monotonic_set {
  set<pair<T, T>> s;
  void add(T x, T val) {
    auto it = s.upper_bound({x, val});
    if (it != s.begin()) {
      auto prv = it;
      prv--;
      if (prv->second >= val) return;
      if (prv->first == x) it = prv;
    }
    auto nxt = it;
    while (nxt != s.end() && val >= nxt->second) {
      nxt++;
    }
    s.erase(it, nxt);
    s.insert({x, val});
  }
  T query(T x) {
    auto it = s.lower_bound({x, INF});
    if (it == s.begin()) return -INF;
    it--;
    return it->second;
  }
};
monotonic_set<int> S[N];
int main() {
  int n, m, u, v, w;
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= n; i++) {
    S[i].add(-1, 0);
  }
  int ans = 0;
  for (int i = 0; i < m; i++) {
    scanf("%d%d%d", &u, &v, &w);
    int f = S[u].query(w);
    S[v].add(w, f + 1);
    cmax(ans, f + 1);
  }
  printf("%d\n", ans);
  return 0;
}
