// Original C++ solution (slower):


#include <bits/stdc++.h>

#define inf INFINITY

#define file freopen( "input.txt" , "r" , stdin) ; freopen( "output.txt" , "w" , stdout) ;

#define Gamed ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);

#define _3102_ main()

#define endl '\n'

typedef long long ll;

typedef unsigned long long ull;

typedef long double ld;

using namespace std;

const int N = 1e5 + 100;

const ll MX = 1e18;

const ll mod = 1e9 + 7;

const double eps = 1e-9 ;

int n , m , dp[N] ;

vector < int > adj[N] ; 



int solve( int node ){

    //cout << node << endl ; 

    if ( dp[node] != -1 ) return dp[node] ;

    int maxi = 0 ; 

    for ( auto j : adj[node]){

        maxi = max ( maxi , solve(j) + 1 ) ;

    }

    return dp[node] = maxi ; 

} 



int _3102_{

	Gamed

    cin >> n >> m ; 

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

        int u , v ; 

        cin >> u >> v ;

        adj[v].push_back(u) ; 

    }

    //for ( int i = 1 ; i <= n ; i ++){

    //    cout << i << ": " ; 

    //    for ( auto j : adj[i] ){

    //        cout << j << " " ;

    //    }

    //    cout << endl ; 

    //}

    memset ( dp , -1 , sizeof dp ) ;

 

    for ( int i = 1 ; i <= n ; i ++){

        if ( dp[i] == -1 ){

            //cout << "--" << i << "--" << endl  ;

            solve (i) ;

            //cout << "------\n";

            //for ( int j = 1 ; j <= n ; j ++ ) cout << dp[j] << " " ;

            //cout << "\n------\n" ;  

        }  

    }

    int ans= 0 ; 

    for ( int i = 1 ; i <= n ; i ++ ){

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

    }

    cout << ans << endl ; 

    return 0;

}




// Optimized solution to the same problem (faster):
#include <bits/stdc++.h>

#define eps 1e-3

#define pi acos(-1.0)

#define inf 0x3f

#define INF 0x3f3f3f3f

#define pb push_back

#define debug1 cout<<"&&";

#define debug2 cout<<"**";

#define ms(a, x) memset(a, x, sizeof(a))

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

#define for1(i, n) for(int i = 1; i <= n; ++i)

using namespace std;

typedef double db;

typedef long long ll;

typedef unsigned long long ull;

typedef pair<int, int> pii;

typedef pair<long long, int> pli;

typedef pair<long long, long long> pll;

const int mod = 1e9 + 7;

const int N = 1e5+10;

const int M = 1e6+10;

inline int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }

inline ll Pow(ll a, ll b) { ll ans = 1; for( ; b; b >>= 1) { if(b&1) ans = ans * a % mod; a = a * a % mod;} return ans;}

inline ll Mul ( ll a, ll b)  { ll lf = a * ( b >> 25ll ) % mod * ( 1LL << 25 ) % mod; ll rg = a * ( b & ( ( 1ll << 25 ) - 1 ) ) % mod; return ( lf + rg ) % mod;}

inline ll C(ll y, ll x) { ll ans = 1; if(y < 0 || x < 0 || y < x) return 0; y %= mod; if(!y || !x) return 1; for0(i, x) ans = ans * (y-i) % mod; for1(i, x) ans = ans * Pow(i, mod-2) % mod; return ans; }

//==================================================================================================================================================================//



int n, m, tot, head[N], nex[N], ver[N];

int dp[N], deg[N], ans;

queue<int> q;



void add(int x, int y) {

   ver[++tot] = y, nex[tot] = head[x], head[x] = tot;

}



int main() {

   scanf("%d %d", &n, &m);

   for1(i, m) {

      int x, y;

      scanf("%d %d", &x, &y);

      add(x, y);

      deg[y]++;

   }

   for1(i, n) if(!deg[i]) q.push(i);

   while(!q.empty()) {

      int x = q.front(); q.pop();

      for(int i = head[x]; i; i = nex[i]) {

         int y = ver[i]; deg[y]--;

         dp[y] = max(dp[y], dp[x] + 1);

         if(!deg[y]) q.push(y);

      }

   }

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

   printf("%d\n", ans);

   return 0;

}

// Fastest known solution for this problem: