#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 300001;
const int MAX_M = 300001;
const int MAX = 21474836;
typedef struct _my_graph_t {
  int from;
  int to;
  int w;
} my_graph_t;
typedef struct _my_weight_t {
  int w;
  int num;
  int start;
} my_weight_t;
my_graph_t graph[MAX_M], origin[MAX_M];
my_weight_t weight[MAX_M];
int weight_num[MAX_M];
int result[MAX_N], r_tmp[MAX_N];
int process() {
  int n, m;
  scanf("%d%d", &n, &m);
  memset(weight_num, 0, sizeof(weight_num));
  int edge_num = 0;
  int from, to, w;
  int min_weight = MAX, max_weight = 0;
  for (int i = 0; i < m; ++i) {
    scanf("%d%d%d", &from, &to, &w);
    weight_num[w]++;
    origin[i].from = from;
    origin[i].to = to;
    origin[i].w = w;
    min_weight = min_weight < w ? min_weight : w;
    max_weight = max_weight > w ? max_weight : w;
  }
  int cur = 0;
  int total = 0;
  int index[MAX_M];
  for (int i = min_weight; i <= max_weight; ++i) {
    if (weight_num[i] == 0) {
      continue;
    }
    index[i] = cur;
    weight[cur].w = i;
    weight[cur].num = weight_num[i];
    weight[cur].start = total;
    total += weight_num[i];
    cur++;
  }
  for (int i = 0; i < cur; ++i) {
  }
  int tmp_num[cur + 1];
  memset(tmp_num, 0, sizeof(tmp_num));
  for (int i = 0; i < m; ++i) {
    w = origin[i].w;
    int pos = weight[index[w]].start + tmp_num[index[w]];
    graph[pos].from = origin[i].from;
    graph[pos].to = origin[i].to;
    graph[pos].w = origin[i].w;
    tmp_num[index[w]]++;
  }
  total = cur;
  memset(result, 0, sizeof(result));
  memset(r_tmp, 0, sizeof(r_tmp));
  int value = 0;
  for (int i = 0; i < total; ++i) {
    int start = weight[i].start;
    int end = weight[i].start + weight[i].num;
    for (int k = start; k < end; ++k) {
      r_tmp[graph[k].to] = result[graph[k].to];
    }
    for (int k = start; k < end; ++k) {
      to = graph[k].to;
      from = graph[k].from;
      r_tmp[to] = r_tmp[to] > result[from] + 1 ? r_tmp[to] : result[from] + 1;
    }
    for (int k = start; k < end; ++k) {
      to = graph[k].to;
      result[to] = r_tmp[to];
      value = value > result[to] ? value : result[to];
    }
  }
  return value;
}
int main() {
  int result = process();
  cout << result << endl;
}
