// Slower C++ solution:
#include <iostream>

#include <algorithm>

#include <cmath>

#include <limits>

#include <vector>

#include <cstdio>

#include <bits/stdc++.h>

#include <set>

#include <map>

#include <stdio.h>

#include <stack>

#include <queue>

#include <deque>

#include <numeric>

#include <bits/stdc++.h>

#include <utility>

#include <iomanip>



#define ALL(obj) (obj).begin(), (obj).end()

#define FOR(i,a,b) for(int i = (a); i < (b); i++)

#define RFOR(i,a,b) for(int i = (a); (b) <= i; i--)

#define REP(i,n) for(int i = 0; i < (n); i++)

#define RREP(i,n) for(int i = n; n <= i; i--)

#define ABS(a) ((a < 0) ? ((-1)*(a)) : (a))

#define elif else if

#define MOD 1000000007

#define INF (1<<29)



using namespace std;



#define ld long double

#define ll long long



map <int ,int> mpa,mpb;

typedef pair<ll, ll> P;

priority_queue<P, vector<P>, greater<P>> pque;



const int N_MAX=100100;

vector<int> g[N_MAX];

int dp[N_MAX];

int N,M;

bool used[N_MAX];



int dfs(int s){

  if(used[s]) return dp[s];

  used[s]=true;

  int ret=0;

  for(auto t:g[s]){

    ret=max(ret,dfs(t)+1);

  }

  return dp[s]=ret;

}





int main(){

  ios::sync_with_stdio(false);

  cin.tie(NULL);



  cin >> N >> M;



  int x[N_MAX],y[N_MAX];

  for(int i=0;i<N_MAX;i++){

    used[i]=false;

  }



  /*for(int i=0;i<N_MAX;i++){

    for(int j=0;j<N_MAX;j++){

      x[i][j]=0;

      //if(i==j)x[i][j]==1;

    }

  }*/





  for(int i=0;i<N_MAX;i++){

    dp[i]=0;

  }

  //int x,y;

  for(int i=0;i<M;i++){

    cin >> x[i] >> y[i];

    x[i]--;

    y[i]--;

    g[x[i]].push_back(y[i]);

  }



  int ans=0;

  for(int i=0;i<N;i++){

    ans=max(ans,dfs(i));

  }

  cout << ans << endl;

  return 0;

}




// Faster C++ solution for the same problem (measured speedup: 0.9200977265366248x):
#include <iostream>

#include <algorithm>

#include <cmath>

#include <limits>

#include <vector>

#include <cstdio>

#include <bits/stdc++.h>

#include <set>

#include <map>

#include <stdio.h>

#include <stack>

#include <queue>

#include <deque>

#include <numeric>

#include <bits/stdc++.h>

#include <utility>

#include <iomanip>



#define ALL(obj) (obj).begin(), (obj).end()

#define FOR(i,a,b) for(int i = (a); i < (b); i++)

#define RFOR(i,a,b) for(int i = (a); (b) <= i; i--)

#define REP(i,n) for(int i = 0; i < (n); i++)

#define RREP(i,n) for(int i = n; n <= i; i--)

#define ABS(a) ((a < 0) ? ((-1)*(a)) : (a))

#define elif else if

#define MOD 1000000007

#define INF (1<<29)



using namespace std;



#define ld long double

#define ll long long



map <int ,int> mpa,mpb;

typedef pair<int, int> P;

priority_queue<P, vector<P>, greater<P>> pque;



int N,M;

bool visited[100100];

int dp[100100]={0};

vector<int> G[100100],v;



void dfs(int s){

  visited[s]=1;

  for(int i=0;i<G[s].size();i++){

    if(!visited[G[s][i]]){

      dfs(G[s][i]);

    }

  }

  v.push_back(s);

}



int main(){

  ios::sync_with_stdio(false);

  cin.tie(NULL);

  cin >> N >> M;

  int x,y;

  for(int i=0;i<M;i++){

    cin >> x >> y;

    x--;

    y--;

    G[x].push_back(y);

  }



  for(int i=0;i<N;i++){

    if(!visited[i]){

      dfs(i);

    }

  }

  reverse(v.begin(),v.end());



  int ans=0;

  for(int i=0;i<N;i++){

    for(int j=0;j<G[v[i]].size();j++){

      dp[G[v[i]][j]]=max(dp[G[v[i]][j]],dp[v[i]]+1);

    }

    ans=max(ans,dp[v[i]]);

  }

  cout << ans << endl;

  return 0;

}