#include <bits/stdc++.h>
using namespace std;
long long mod = 1000000007, oo = 1000000009;
void Emsawy() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
}
int dx[] = {1, -1, 0, 0, 1, -1, 1, -1};
int dy[] = {0, 0, 1, -1, 1, -1, -1, 1};
const long long N = 210000 + 5;
long long n, m, k, w;
struct edge {
  vector<int> adj;
  vector<int> BIT;
  void build() {
    sort(((adj).begin()), ((adj).end()));
    BIT.resize(adj.size() + 100);
  }
  int getInd(int val) {
    return upper_bound(((adj).begin()), ((adj).end()), val) - adj.begin() - 1;
  }
  void upd(int idx, int vl) {
    idx++;
    for (int id = idx; id < BIT.size(); id += (id & -id)) {
      BIT[id] = max(BIT[id], vl);
    }
  }
  int query(int idx) {
    idx++;
    int ret = 0;
    for (int id = idx; id > 0; id -= (id & -id)) {
      ret = max(ret, BIT[id]);
    }
    return ret;
  }
};
vector<edge> g;
int main() {
  Emsawy();
  while (cin >> n >> m) {
    g.clear();
    g.resize(n + 1);
    int u, v, w;
    vector<pair<int, int> > ed;
    vector<int> val;
    for (int i = 0; i < m; i++) {
      cin >> u >> v >> w;
      g[v].adj.push_back(w);
      ed.push_back({u, v});
      val.push_back(w);
    }
    for (int i = 1; i <= n; i++) {
      g[i].build();
    }
    int mx = 0;
    for (int i = 0; i < m; i++) {
      int u = ed[i].first, v = ed[i].second, w = val[i];
      int pos = g[u].getInd(w);
      int ans = g[u].query(pos) + 1;
      g[v].upd(g[v].getInd(w), ans);
      mx = max(mx, ans);
    }
    cout << mx << endl;
  }
  return 0;
}
