#include <bits/stdc++.h>
using namespace std;
vector<int> adj[(int)1e6];
vector<int> inset[(int)1e6];
int n, m;
int dp[(int)1e6];
int main() {
  scanf("%d%d", &n, &m);
  memset(dp, 0, sizeof dp);
  vector<pair<int, pair<int, int> > > edges;
  for (int i = 0; i < m; i++) {
    int x, y, w;
    scanf("%d%d%d", &x, &y, &w);
    x--, y--;
    edges.push_back(pair<int, pair<int, int> >(w, pair<int, int>(x, y)));
  }
  sort(edges.rbegin(), edges.rend());
  int ans = 0;
  int currw = 0;
  stack<pair<int, int> > hold;
  while (!edges.empty()) {
    pair<int, pair<int, int> > u = edges.back();
    if (currw != u.first) {
      currw = u.first;
      while (hold.size()) {
        if (hold.top().second < dp[hold.top().first]) {
          hold.pop();
          continue;
        }
        dp[hold.top().first] = hold.top().second;
        ans = max(ans, hold.top().second);
        hold.pop();
      }
    }
    edges.pop_back();
    if (dp[u.second.second] < dp[u.second.first] + 1)
      hold.push(pair<int, int>(u.second.second, dp[u.second.first] + 1));
    ans = max(ans, dp[u.second.second]);
  }
  while (hold.size()) {
    if (hold.top().second < dp[hold.top().first]) {
      hold.pop();
      continue;
    }
    dp[hold.top().first] = hold.top().second;
    ans = max(ans, hold.top().second);
    hold.pop();
  }
  printf("%d\n", ans);
}
