#include <bits/stdc++.h>
using namespace std;
class nodes {
  set<long int> st;
  vector<long int> v, seg;
  long int n;

 public:
  nodes() {
    n = 0;
    st.clear();
    v.clear();
    seg.clear();
  }
  void push(long int p) { st.insert(p); }
  void build() {
    set<long int>::iterator it;
    n = 0;
    for (it = st.begin(); it != st.end(); it++) {
      v.push_back(*it);
      n++;
    }
    long int i;
    for (i = 0; i < 2 * n; i++) {
      seg.push_back(0);
    }
  }
  long int bs(long int w) {
    long int l = 0, r = n - 1, mid;
    while (l <= r) {
      mid = (l + r) / 2;
      if (v[mid] == w) {
        return mid;
      } else if (v[mid] < w) {
        l = mid + 1;
      } else {
        r = mid - 1;
      }
    }
    return 0;
  };
  void update(long int w, long int v) {
    long int p = bs(w);
    p = p + n;
    seg[p] = max(seg[p], v);
    while (p > 1) {
      p >>= 1;
      seg[p] = max(seg[2 * p], seg[2 * p + 1]);
    }
  };
  long int query(long int w) {
    long int res = 0;
    long int l, r, p;
    p = bs(w);
    l = n;
    r = n + p;
    for (; l < r; l >>= 1, r >>= 1) {
      if (l & 1) res = max(res, seg[l++]);
      if (r & 1) res = max(res, seg[--r]);
    }
    return res;
  }
} nds[1000007];
int main() {
  long int n, m, mx = 1, cur;
  cin >> n >> m;
  long int i;
  long int a[m], b[m], w[m];
  for (i = 0; i < m; i++) {
    cin >> a[i] >> b[i] >> w[i];
    nds[a[i]].push(w[i]);
    nds[b[i]].push(w[i]);
  }
  for (i = 0; i <= n; i++) {
    nds[i].build();
  }
  for (i = 0; i < m; i++) {
    cur = nds[a[i]].query(w[i]);
    mx = max(cur + 1, mx);
    nds[b[i]].update(w[i], cur + 1);
  }
  cout << mx;
  return 0;
}
