// Original C++ solution (slower):
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

typedef unsigned long long ull;

typedef pair<ll,ll>pll;

typedef pair<ll,pair<ll,ll>>plll;

#define fastread() (ios_base:: sync_with_stdio(false),cin.tie(NULL));

#define vll(v) v.begin(),v.end()

#define all(x) x.rbegin(),x.rend()

#define min3(a, b, c)   min(a, min(b, c))

#define max3(a, b, c)   max(a, max(b, c))

#define F first

#define S second

#define in  freopen("input.txt", "r", stdin)

#define out  freopen("output.txt", "w", stdout)

#define minheap int,vector<int>,greater<int>

#define pb push_back

#define eb emplace_back

#define ischar(x)  (('a' <= x && x <= 'z') || ('A' <= x && x <= 'Z'))

#define isvowel(ch) ((ch=='a'||ch=='e'||ch=='i'||ch=='o'||ch=='u')||(ch=='A'|| ch=='E' || ch=='I'|| ch=='O'|| ch=='U'))

#define bug cout<<"BUG"<<endl;

const int Max = 1e5 + 10;

const int Mod = 1e9 + 7;

const double PI  =3.141592653589793238463;





ll n,m;



vector<ll>adj[Max+10];



ll indeg[Max+10];



ll dis[Max+10];







void input()

{

      ll i,a,b;





       for(i=1; i<=m; i++)

       {

           cin>>a>>b;



           adj[a].eb(b);



           indeg[b]++;

       }

}



ll topsort()

{

    ll u,mx=0;



       queue<ll>q;



       for(ll i=1; i<=n; i++)

       {

           if(!indeg[i])q.push(i);

       }



         while(!q.empty())

         {

              u=q.front();



              q.pop();



                for(auto v  : adj[u])

                {

                   dis[v]=max(dis[v],dis[u]+1);



                   mx=max(dis[v],mx);



                   indeg[v]--;



                   if(!indeg[v])

                    q.push(v);

                }

         }



         return mx;

}

int main()

{



   fastread();



   ll i,j,p,a,sum=0,k,t,b,c,d,cnt=0,q,l,r;





     string str;



   bool flag=true;



     cin>>n>>m;



     input();





      cout<<topsort()<<endl;















}




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

#define ll          long long int

#define ld          long double

#define pb          push_back

#define mp          make_pair

#define ff          first

#define se          second

#define scan(n)     scanf("%lld", &n);

#define print(n)    printf("%lld\n", n);

#define fd(n)       fixed<<setprecision(n)

#define MAX         1000000000000000000

#define MAXN        100005

#define LOG         19

#define mod         1000000007

using namespace std;





int main(){

    ios_base::sync_with_stdio(false);

    cin.tie(NULL);

    ll n,m,i,x,y,mx=0;

    cin>>n>>m;

    vector<ll> vi[n+1];

    ll deg[n+1];

    queue<ll> qe;

    vector<ll> vi1;

    memset(deg,0,sizeof(deg));

    for(i=1;i<=m;i++){

        cin>>x>>y;

        vi[x].pb(y);

        deg[y]++;

    }

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

        if(deg[i]==0){

            qe.push(i);

            vi1.pb(i);

        }

    }

    while(!qe.empty()){

        ll node=qe.front();

        qe.pop();

        for(auto x:vi[node]){

            deg[x]--;

            if(deg[x]==0){

                vi1.pb(x);

                qe.push(x);

            }

        }

    }

    ll dp[n+1];

    memset(dp,0,sizeof(dp));

    for(auto node:vi1){

        for(auto x:vi[node]){

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

        }

    }

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

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

    }

    cout<<mx;

}

// Fastest known solution for this problem: