#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp> 
#include <ext/pb_ds/tree_policy.hpp> 
 
using namespace std;
using namespace __gnu_pbds;
 
 
#define pb push_back
#define mp make_pair
#define lb lower_bound
#define ub upper_bound
#define f first
#define s second
#define resz resize
#define ini ll_MAX
#define inl LLONG_MAX
#define MOD 1000000007
#define sz(x) ll((x).size())
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define FOR(i, a, b) for (ll i = (a); i < (b); i++)
#define F0R(i, a) for (ll i = 0; i < (a); i++)
#define FORR(i, a, b) for (ll i = a; i >= (b); i--)
#define F0RR(i, a) for (ll i = a; i >= 0; i--)
#define trav(a, x) for (auto& a : x)
#define pbds tree<ll, null_type,less<ll>, rb_tree_tag,tree_order_statistics_node_update> 
 
using ll = long long;
using vi = vector<ll>;
using vvi = vector<vi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using vb = vector<bool>;
using vd = vector<double>;
using vs = vector<string>;
 
using pii = pair<ll, ll>;
using pll = pair<ll, ll>;
using pdd = pair<double, double>;
 
using vpii = vector<pii>;
using vvpii = vector<vpii>;
using vpll = vector<pll>;
using vvpll = vector<vpll>;
using vpdd = vector<pdd>;
using vvpdd = vector<vpdd>;
 


// ll Arr[105];
// ll Size[105];


// ll root (ll i)
// {
//     while(Arr[ i ] != i)
//     {
//         Arr[ i ] = Arr[ Arr[ i ] ] ; 
// i = Arr[ i ]; 
//     }
// return i;
// }


// void initialize(ll N)
// {
//     for(ll i = 0;i<N;i++)
//     {
//         Arr[ i ] = i ;
//         Size[ i ] = 1;
//     }
// }
// void weighted_union(ll A,ll B)
// {
//     ll root_A = root(A);
//     ll root_B = root(B);
//     if(Size[root_A] < Size[root_B ])
//     {
// Arr[ root_A ] = Arr[root_B];
// Size[root_B] += Size[root_A];
// }
//     else
//     {
// Arr[ root_B ] = Arr[root_A];
// Size[root_A] += Size[root_B];
// }

// }

ll mod(ll a,ll b)
{
    return (b+a%b)%b;
}
 
ll gcd(ll a,ll b)
{
    if(b==0)return a;
    else return gcd(b,a%b);
}
ll po(ll a,ll b)
{
    ll ans = 1;
    while(b--)
        ans*=a;
    return ans;
}
ll power(ll a,ll b,ll c)
{
    ll x=1,y=a;
    while(b > 0)
    {
        if(b%2 == 1)
        {
            x=(x*y)%c;
        }
        y = (y*y)%c;
        b /= 2;
    }
    return x%c;
}
 
double sqdist(double a,double b,double c,double d)
{
    return (a-c)*(a-c)+(b-d)*(b-d);
}
ll fact(ll n)
{
    if(n==0)return 1;
    ll ans = 1;
    FOR(i,1,n+1)ans*=i;
    return ans;
}


ll check(ll i)
{
    ll p = 0;
    while(i)
    {
        if(i%2)p++;
        i/=2;
    }
    // cout<<i<<' '<<p<<endl;
    return p;
}

vector<int> vec[100005];

void solve()
{
    int n,m;
    set<int> s;
    cin>>n>>m;
    // cout<<n<<' '<<m<<endl;
    vector<int> dp(n+1,0);
    vector<int> in(n+1,0);
    for(int i=0;i<m;i++)
    {
        int a,b;
        cin>>a>>b;
        vec[a].push_back(b);
        in[b]++;
        // vec[b].push_back(a);
    }
    for(int i=1;i<=n;i++)
    {
        if(!in[i])
            s.insert(i);
    }
    int k = 0;
    int c = 0;
    while(s.size())
    {
        // if(c==20)break;
        c++;
        set<int> st;
        for(auto i:s)
        {
            // cout<<"H"<<' '<<i<<endl;
            for(auto p:vec[i])
            {
                dp[p]=max(dp[p],dp[i]+1);
                in[p]--;
                if(in[p]==0)st.insert(p);
            }
        }
        // for(auto k:st)cout<<k<<' ';cout<<endl;
        // for(auto k:dp)cout<<k<<' ';cout<<endl;
        s=st;
    }
    for(auto i:dp)
        k = max(k,i);
    cout<<k;

}   
 
main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    solve();
}


Measured memory_bytes: 11192