#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
using namespace std;

#define vvi             vector<vector<int>>
#define ld              long double
#define mod             1000000007
#define ff              first
#define ss              second
#define int             long long
#define pb              push_back
#define mp              make_pair
#define pii             pair<int,int>
#define vpii            vector<pair<int,int>>
#define fr(i,a,b)     for(int i = a; i < b; i += 1)
#define all(x)          x.begin(),x.end()
#define sz(a)           (int)(a.size())
#define vi              vector<int>
#define mii             map<int,int>
#define pqb             priority_queue<int>
#define pqs             priority_queue<int,vi,greater<int> >
#define setbits(x)      __builtin_popcountll(x)
#define zrobits(x)      __builtin_ctzll(x)
#define inf             1e18
#define ps(x,y)         fixed<<setprecision(y)<<x
#define mk(arr,n,type)  type *arr=new type[n];
#define w(x)            int x; cin>>x; while(x--)
#define pw(b,p)         pow(b,p) + 0.1
#define input(a)      for(auto it = a.begin(); it != a.end(); it++) { int value; cin >> value; *it = value;}
#define print(a)        for(auto it = a.begin() ; it != a.end() ; it++){ cout << *it << " " ;}cout << '\n';
mt19937                 rng(chrono::steady_clock::now().time_since_epoch().count());
 
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> pbds;
 
#define SS                      stringstream
#define db(...)                 __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1) { cerr << name << " : " << arg1 <<'\n'; }
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args) {
    const char* comma = strchr(names + 1, ',');
    cerr.write(names, comma - names) << " : " << arg1 << " | "; __f(comma + 1, args...);
}
 
int power(int x ,int y )
{
    if( y == 0 )
    return 1;
    
    int temp = power(x,y/2);
    
    if( y % 2 == 0 )
    return temp*temp;
    else
    return x*temp*temp;
}

int fac[22001];
int power(int x, int y, int p) 
{ 
    int res = 1;      // Initialize result 
  
    x = x % p;  // Update x if it is more than or 
                // equal to p 
  
    while (y > 0) 
    { 
        // If y is odd, multiply x with result 
        if (y & 1) 
            res = (res*x) % p; 
  
        // y must be even now 
        y = y>>1; // y = y/2 
        x = (x*x) % p; 
    } 
    return res; 
} 
  
// Returns n^(-1) mod p 
int modInverse(int n, int p) 
{ 
    return power(n, p-2, p); 
} 


// Returns nCr % p using Fermat's little 
// theorem. 
int nCrModPFermat(int n, int r, int p) 
{ 
   // Base case 
   if (r==0) 
      return 1; 
  
    // Fill factorial array so that we 
    // can find all factorial of r, n 
    // and n-r 
     
  
    return (fac[n]* modInverse(fac[r], p) % p * 
            modInverse(fac[n-r], p) % p) % p; 
}
 
int gcd(int a, int b)
{
    return __gcd(a,b);
}
 
int lcm(int a, int b)
{
    return (a*b)/__gcd(a,b);
}
 
void SieveOfEratosthenes(int n) 
{ 
    bool prime[n+1]; 
    memset(prime, true, sizeof(prime)); 
  
    for (int p=2; p*p<=n; p++) 
    { 
        if (prime[p] == true) 
        {  
            for (int i=p*p; i<=n; i += p) 
                prime[i] = false; 
        } 
    } 
  
    // Print all prime numbers 
    for (int p=2; p<=n; p++) 
       if (prime[p]) 
          cout << p << " "; 
} 

void FASTIO()
{
	ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
}

bool isPrime(int n)
{
    for(int i = 2; i*i <= n; i++)
    {
        if(n % i == 0)
        return false;
    }
    
    return true;
}

vvi v;
int n, m;
vi d;
vi in;
vi vis;

void dfs(int node)
{
    if(vis[node] == 1) return;
    
    vis[node] = 1;
    for(auto child : v[node])
    {
        d[child] = max(d[child], d[node] + 1);
        in[child] -= 1;
        
        if(in[child] == 0)
        {
            dfs(child);
        }
    }
}

void test_case()
{
    v.clear();    
    cin >> n >> m;
    v.clear();
    v = vvi(n);
    d = vi(n, 0);
    vis = vi(n, 0);
    in = vi(n, 0);
    for(int i = 0; i < m; i++)
    {
        int a, b;
        cin >> a >> b;
        a--;
        b--;
        v[a].pb(b);
        in[b] += 1;
    }
    
    for(int i = 0; i < n; i++)
    if(vis[i] == 0 && in[i] == 0)
    dfs(i);
    
    cout << *max_element(d.begin(), d.end());
}

int32_t main()
{
	FASTIO();
    //w(t)
    {
        test_case();
    }
	return 0;
}

Measured memory_bytes: 11264