#include <bits/stdc++.h>
const int maxn = 1e5 + 5;
class SegTree {
 private:
  struct node {
    int val;
    node *ch[2];
    node() {
      val = 0;
      ch[0] = ch[1] = NULL;
    }
    inline void update() {
      val = 0;
      if (ch[0] != NULL && ch[0]->val > val) val = ch[0]->val;
      if (ch[1] != NULL && ch[1]->val > val) val = ch[1]->val;
    }
  };

 public:
  struct node *root;
  SegTree() { root = NULL; }
  void update(node *&now, int l, int r, int to, int x) {
    if (now == NULL) now = new node();
    if (l == r) {
      now->val = std::max(x, now->val);
      return;
    }
    int mid = l + r >> 1;
    if (to <= mid) update(now->ch[0], l, mid, to, x);
    if (to > mid) update(now->ch[1], mid + 1, r, to, x);
    now->update();
  }
  int query(node *now, int l, int r, int to) {
    if (to < l) return 0;
    if (now == NULL) return 0;
    if (r <= to) return now->val;
    int mid = l + r >> 1;
    if (to > mid)
      return std::max(query(now->ch[0], l, mid, to),
                      query(now->ch[1], mid + 1, r, to));
    else
      return query(now->ch[0], l, mid, to);
  }
};
class SegTree tree[maxn];
int n, m, Max;
inline void read(int &now) {
  char Cget;
  now = 0;
  while (!isdigit(Cget = getchar()))
    ;
  while (isdigit(Cget)) {
    now = now * 10 + Cget - '0';
    Cget = getchar();
  }
}
int main() {
  read(n);
  read(m);
  for (int i = 1, u, v, w; i <= m; i++) {
    read(u);
    read(v);
    read(w);
    tree[v].update(tree[v].root, 0, 100000, w,
                   tree[u].query(tree[u].root, 0, 100000, w - 1) + 1);
  }
  for (int i = 1; i <= n; i++)
    Max = std::max(Max, tree[i].query(tree[i].root, 0, 100000, 100000));
  std::cout << Max << std::endl;
  return 0;
}
