#include <bits/stdc++.h>
#include <vector>
#include <set>
#include <map>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <climits>
#include <utility>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <iomanip>
#include <string>
#include <stack>
 
using namespace std;
 
#define f(i,a,b) for(int i=a;i<b;i++)
#define fll(i,a,b) for(ll i=a;i<b;i++)
#define rep(i,n) f(i,0,n)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define pb push_back
#define mp make_pair
#define vi vector< int >
#define vl vector< ll >
#define vvi vector<vector<int> >
#define ss second
#define ff first
#define ll long long
#define lld long double
#define pii pair< int,int >
#define pll pair< ll,ll >
#define sz(a) a.size()
#define inf (1000*1000*1000+5)
#define all(a) a.begin(),a.end()
#define tri pair<int,pii>
#define vii vector<pii>
#define vll vector<pll>
#define viii vector<tri>
#define mod (1000*1000*1000+7)
#define pq priority_queue< int >
#define pqll priority_queue< ll >
#define pdqueue priority_queue< int,vi ,greater< int > >
#define INF 1000000000
#define NINF -1000000000
 
ll maxll(ll a , ll b ){
    return a > b ? a : b;
}
 
ll minll(ll a , ll b){
    return a > b ? b : a;
}

// bool check(ll z){
//     ll temp = k;
//     // cout << z << endl;
//     f(i , 0 , n){
//         ll sub = (ll)z * a[i];
//         if (sub > b[i])
//         temp -= (sub -b[i]);
//         if (temp < 0){
//             return 0;
//         }
//     }
//         // cout << z << endl;
//     sol = z;
//         return 1;
// }

// int gcd (int a , int b){
//     return __gcd(a,b);
// }

// void print_vi(vi a){
//     for (int i: a){
//         cout << i << " " ;
//     }
//     cout << endl;
// }

// Best algo to find maximum sum subarray (contiguous)
// ll kadane (vl a){
//     ll curr = 0 , maxi = 0;
//     f(i , 0 , a.size()){
//         curr = max(a[i] , curr + a[i]);
//         maxi = max(maxi , curr);
//     }
//     return maxi;
// }

// Method to get the factors of a big number here a[j] = factors of number j
// ll x;
// cin >> x;
// vl a(x+1 , 0);
// f( i , 1 , x+1){
//     for (int j = i ; j < x+1 ; j+= i){
//         a[j]++;
//     }
// }


// void printGraph(vector<int> adj[], int V) 
// { 
//     for (int v = 0; v < V; ++v) 
//     { 
//         cout << "\n Adjacency list of vertex "
//              << v << "\n head "; 
//         for (auto x : adj[v]) 
//            cout << "-> " << x; 
//         printf("\n"); 
//     } 
// }

int n , m;
vector <bool> visited(1e5  + 7);
const int N = 1e5 + 7;
vi adj[N];
vi in_degree(N);
vi dp(N,0);

void dfs(int a){
    visited[a] = true;
    for(auto i : adj[a]){
        dp[i] = max(dp[i] , dp[a]+1);
        in_degree[i]--;
        if(in_degree[i] == 0){
            dfs(i);
        }
    }
}


void solve(){
    
    cin >> n >> m;
    int a , b;
    
    f( i , 0 , m){
        cin >> a >> b;
        adj[a].pb(b);
        in_degree[b]++;
        // adj[n].pb(b);
        // cout << adj[a][0] << adj[a][1];
    }
    for (int i = 1 ; i <= n ; i++){
        if (!visited[i] && in_degree[i] == 0){
            dfs(i);
        }
    }

    int ans = 0;
    f( i , 1 , n+1){
        ans = max(ans , dp[i]);
    }
    cout << ans << endl;

    // printGraph(adj , n);
    
    
}

 
int main(){
    ios::sync_with_stdio(0);
    cin.tie(nullptr);
    cout.tie(nullptr);
    cerr.tie(nullptr);
 
 
    
    int t = 1;
    // cin >> t;
    
    while(t--){
        
        solve();
    }
}

Measured memory_bytes: 14160