// 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: 1.149448631112839x):
#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;



vector<ll> G[100100];

ll dp[100100];

bool used[100100];



ll dijkstra(ll s){

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

  for(auto e:G[s]){

    dp[s]=max(dp[s],dijkstra(e)+1);

  }

  used[s]=true;

  return dp[s];

}



int main(){

  ios::sync_with_stdio(false);

  cin.tie(NULL);

  ll N,M;

  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++){

    dp[i]=0;

  }

  ll ans=0;

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

    ans = dijkstra(i);

  }

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

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

  }

  cout << ans << endl;

  return 0;

}