//#pragma GCC optimize("Og,no-stack-protector,unroll-loops,fast-math")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include <bits/stdc++.h>
//#include <boost/multiprecision/cpp_int.hpp>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
using namespace std;
//using namespace boost::multiprecision;
using namespace __gnu_pbds;
template <typename T>
using os = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
typedef long long  ll;
typedef double ld;
#define ios ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
#define rep(i,a,b) for(int i=a;i<b;i++)
#define rrep(i,a,b) for(int i=a;i>=b;i--)
#define pii pair<ll,ll>
#define vi  vector<ll>
#define vii vector<pii >
#define mi  map<ll,ll>
#define all(a)  (a).begin(),(a).end()
#define pb push_back
#define make make_pair
#define ff first
#define ss second
#define osl os<ll>
#define ospii os<pair<ll,ll> >
#define endl "\n"
template <typename  R>
void println(R r){
    for(auto i:r)
        cout<<i<<" ";
    cout<<endl;

}
template <typename  R>
void print(R r){
    for(auto i:r)
        cout<<i<<endl;
}
ll st[200005]={0},ft[200005]={0},parent[200005],tt=0,level[100005]={0},fans=0;
set<ll> st1,st2;
ll binexp(ll a,ll b,ll m)
{
    ll ans=1;
    while(b)
    {
        if(b&1)
            ans=(ans*a)%m;
        b/=2;
        a=(a*a)%m;
    }
    return ans;
}
ll dp[100001];
void dfs(vi graph[],ll start,ll *visit){
    visit[start]=1;
    // level[0]=0;
    st[start]=tt;
    tt++;
    for(auto child:graph[start]){
        parent[child]=start;
     //   if(!visit[child]){
            visit[child]=1;
            level[child]=level[start]+1;
            // v.pb(child);
            if(dp[child]==-1) {
                dfs(graph, child, visit);
            }
            dp[start]=max(dp[start],dp[child]+1);

       // }
    }
    if(graph[start].size()==0)
        dp[start]=0;
    ft[start]=tt;

}

int bfs1(multiset<ll> graph[],ll *visit,ll *level,vi &v){
    multiset<ll> q;
    ll start=1;
    q.insert(start);
    level[start]=0;
    visit[start]=1;
    while(q.size()!=0){
        ll p=*q.begin();
        q.erase(q.begin());
        v.pb(p);
        for(auto it=graph[p].begin();it!=graph[p].end();it++){
            level[(*it)]=min(level[*it],level[p]+1);
            if(visit[(*it)]!=1){
                q.insert((*it));
                visit[(*it)]=1;


            }
        }

    }
}
/*
ll dp[1001][1001];
ll calc(set<ll> &st,ll i,ll j,ll *alr_col,ll k){
    if(dp[i][j]!=-1)
        return dp[i][j];
    else{
        ll ans=0;
        for(auto it=st.begin();it!=st.end();it++){
            ll p=*it;
            if(dp[p][j-1])
            if(binary_search(alr_col,alr_col+k,p-1)==true)
                st.insert(p-1);
            if(binary_search(alr_col,alr_col+k,p+1)== true)
                st.insert(p+1);
            st.erase(it);

            ans+=calc(st, p, st.size(),alr_col,k);

        }
    }
}*/
clock_t time_p=clock();
void mr_TLL()
{
    time_p=clock()-time_p;
    cerr<<"Time Taken : "<<(float)(time_p)/CLOCKS_PER_SEC<<"\n";
}
int main(){
    ios
    /*
    memset(dp,-1, sizeof(dp));
    rep(i,0,1001){
        dp[i][1]=1;
        dp[i][0]=0;
    }
    ll n,k;
    cin>>n>>k;
    ll alr_col[k];
    for(auto i:alr_col)
        cin>>i;
    sort(alr_col,alr_col+k);
    set<ll> v;
    rep(i,0,k){
      if(alr_col[i]+1<n)
          v.insert(alr_col[i]+1);
      if(alr_col[i]-1>=0)
          v.insert(alr_col[i]-1);
    }
    ll ans=0;
    for(auto it=v.begin();it!=v.end();it++) {
        ll p=*it;
        if(binary_search(alr_col,alr_col+k,p-1)==true)
            v.insert(p-1);
        if(binary_search(alr_col,alr_col+k,p+1)== true)
            v.insert(p+1);
        v.erase(it);
        ans+=calc(v, p, v.size());
        */
    ll n,m;
    cin>>n>>m;
    vi graph[n+1];
    while(m--){
        ll x,y;
        cin>>x>>y;
        graph[x].pb(y);
    }
    ll visit[n+1];
    fill(visit,visit+n+1,0);
    fill(dp,dp+100001,-1);
    rep(i,1,n+1){
        if(visit[i]==0)
        dfs(graph,i,visit);
    }
    ll ans=-INT_MAX;
    rep(i,1,n+1)
    ans=max(ans,dp[i]);
    cout<<ans<<endl;
       mr_TLL();



}















Measured memory_bytes: 16000