#include <bits/stdc++.h>
using namespace std;
struct Node {
  Node *le, *ri;
  int val;
  Node(int val = 0) : val(val), le(0), ri(0) {}
};
vector<tuple<int, int, int> > edge;
int n, m;
Node *root[100005];
void update(int idx, int val, int nodele, int noderi, Node *node) {
  if (idx < nodele || noderi < idx) return;
  if (nodele == noderi) {
    node->val = val;
    return;
  }
  int mid = (nodele + noderi) / 2;
  if (node->le == 0) node->le = new Node();
  if (node->ri == 0) node->ri = new Node();
  update(idx, val, nodele, mid, node->le);
  update(idx, val, mid + 1, noderi, node->ri);
  node->val = max(node->le->val, node->ri->val);
}
int query(int le, int ri, int nodele, int noderi, Node *node) {
  if (le > noderi || ri < nodele) return 0;
  if (le <= nodele && noderi <= ri) return node->val;
  int mid = (nodele + noderi) / 2;
  if (node->le == 0) node->le = new Node();
  if (node->ri == 0) node->ri = new Node();
  return max(query(le, ri, nodele, mid, node->le),
             query(le, ri, mid + 1, noderi, node->ri));
}
int main() {
  scanf("%d%d", &n, &m);
  for (int i = 0; i < m; i++) {
    int a, b, c;
    scanf("%d%d%d", &a, &b, &c);
    edge.emplace_back(a, b, c);
  }
  for (int i = 1; i <= n; i++) root[i] = new Node();
  int ans = 0;
  for (int i = m - 1; i >= 0; i--) {
    int a, b, c;
    tie(a, b, c) = edge[i];
    int cnt = query(c + 1, 100000, 0, 100000, root[b]);
    update(c, cnt + 1, 0, 100000, root[a]);
    ans = max(ans, cnt + 1);
  }
  printf("%d\n", ans);
  return 0;
}
