#include <bits/stdc++.h>
#pragma comment(linker, "/STACK:102400000,102400000")
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
using namespace std;
const int maxn = 1e5 + 5;
map<int, int> st[maxn];
class edge {
 public:
  int l, r, w;
} a[maxn];
void gao(int t) {
  int ans = 1;
  auto it = st[a[t].r].upper_bound(a[t].w);
  if (it != st[a[t].r].end()) ans += it->second;
  auto kk = st[a[t].l].upper_bound(a[t].w);
  if (kk != st[a[t].l].end() && kk->second >= ans) return;
  st[a[t].l][a[t].w] = ans;
  auto pt = st[a[t].l].find(a[t].w);
  map<int, int>::reverse_iterator ka(pt);
  for (; ka != st[a[t].l].rend();) {
    if (ka->second < ans)
      ka = map<int, int>::reverse_iterator(st[a[t].l].erase((++ka).base()));
    else
      break;
  }
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  int i, j, k, m, n, T;
  set<int> t = {1, 2, 3, 4, 5, 6};
  set<int>::reverse_iterator pt;
  cin >> n >> m;
  int ta, tb, tc;
  for (int i = 1; i <= m; ++i) cin >> a[i].l >> a[i].r >> a[i].w;
  for (int i = m; i >= 1; --i) gao(i);
  int ans = 0;
  for (int i = 1; i <= n; ++i)
    for (auto it : st[i]) ans = max(ans, it.second);
  cout << ans << endl;
  return 0;
}
