#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
const int maxm = 5e6 + 5;
int n, m;
struct Edge {
  int u, v, w;
} edge[maxn];
int root, cnt, ls[maxm], rs[maxm], max1[maxm];
void update(int &id, long long l, long long r, long long x, int y) {
  if (l > r) return;
  if (!id) id = ++cnt;
  long long mid = (l + r) / 2;
  if (l == r) {
    max1[id] = max(max1[id], y);
    return;
  }
  if (x <= mid)
    update(ls[id], l, mid, x, y);
  else
    update(rs[id], mid + 1, r, x, y);
  max1[id] = max(max1[ls[id]], max1[rs[id]]);
}
int query(int id, long long l, long long r, long long x, long long y) {
  if (x > y) return 0;
  if (!id) return 0;
  int ans = 0;
  long long mid = (l + r) / 2;
  if (x <= l && r <= y) return max1[id];
  if (x <= mid) ans = max(ans, query(ls[id], l, mid, x, y));
  if (y > mid) ans = max(ans, query(rs[id], mid + 1, r, x, y));
  return ans;
}
int main() {
  int ans = 0;
  long long len = 1e5 + 1;
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= m; i++)
    scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].w), edge[i].w++;
  for (int i = m; i >= 1; i--) {
    int u = edge[i].u, v = edge[i].v, w = edge[i].w;
    long long l = len * (v - 1) + w + 1, r = len * (v - 1) + len;
    long long c = len * (u - 1) + w;
    long long x = query(root, 1, len * len, l, r);
    int y = x + 1;
    update(root, 1, len * len, c, y);
    ans = max(ans, y);
  }
  printf("%d\n", ans);
  return 0;
}
