/*

*/
#include <bits/stdc++.h>
using namespace std;
#define pi                       acos(-1.0)
#define fastio                   ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);cout << setprecision(12)
#define rep(i,a,n)               for (ll i=a;i<n;i++)
#define per(i,a,n)               for (ll i=n-1;i>=a;i--)
#define pb                       push_back
#define mp                       make_pair
#define all(x)                   (x).begin(),(x).end()
#define fi                       first
#define se                       second
#define SZ(x)                    ((ll)(x).size())
#define cin1(x)                  cin >> x
#define cin2(x, y)               cin >> x >> y
#define cin3(x, y, z)            cin >> x >> y >> z
#define cin4(x, y, z, z2)        in >> x >> y >> z >> z2
#define cin5(x, y, z, p, q)      cin >> x >> y >> z >> p >> q
#define cou(x)                   cout << x
#define cous(x)                  cout << x << " "
#define coul(x)                  cout << x << "\n"
#define ret(x)                   return x
#define MAX                      1000000007
#define start                    int main() {   fastio
#define finish                   ret(0); }
#define Test ll _t; cin1(_t); rep(w, 0, _t)
#define minv(v) *min_element(v.begin(),v.end())
#define maxv(v) *max_element(v.begin(),v.end())
#define cntv(v,a) count(v.begin(),v.end(),a)
#define fans(x) \
    if ( x  ) coul("YES"); \
    else coul("NO")
#define mset(x, y) memset(x, y, sizeof(x))
#define fileshow  freopen("input.txt","r",stdin); freopen("output.txt","w",stdout)

struct point{    int x, y, ind;   char ch;  };
typedef long long ll;
typedef vector<ll> VI;
typedef pair<ll,ll> PII;
typedef double db;
//mt19937 mrand(random_device{}());
const ll mod=1000000007;
//ll rnd(ll x) { return mrand() % x;}
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}ret(res);}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
ll Com[1005][1005];
void comfunc(){    for(ll i=0;i<=1000;i++){Com[i][0]=1;for(ll j=1;j<=i;j++){Com[i][j]=(Com[i-1][j-1]+Com[i-1][j])%mod;}}}
ll fact[13];
void factorial() {   fact[0]=1;  rep(i, 1, 12) fact[i]=(fact[i-1]*i);  }
 //for sieve function
//void sieve() {    rep(i, 2, MAX)  {  if (spf[i] == 0) {  spf[i] = i;   sie.pb(i);  }    for (ll j=0; j<SZ(sie) && i*sie[j] <= MAX && sie[j] <= spf[i]; j++)   spf[i * sie[j]] = sie[j]; }   }
bool cmp(point A, point B){   if(A.x != B.x) ret(A.x < B.x);  ret(A.y < B.y);   }
//void segUpdate(ll node, ll b, ll e, ll i, ll newvalue){    if (i > e | i < b){return;} if (b >= i && e <= i) {tree[node] = newvalue; return;} ll Left = node * 2; ll Right = node * 2 + 1;ll mid = (b + e) / 2; segUpdate(Left, b, mid, i, newvalue);segUpdate(Right, mid + 1, e, i, newvalue);tree[node] = tree[Left] + tree[Right];}
//void seqQuery(ll node, ll b, ll e, ll i, ll j){ map<ll,ll>Query; if (i > e || j < b){Query[i][j] = 0; }if (b >= i && e <= j){Query[i][j]= tree[node];} ll mid = (b + e) / 2;ll p1 = segQuery(2*node, b, mid, i, j);ll p2 = segQuery(2*node+1, mid + 1, e, i, j);Query[i][j]= p1 + p2; }
//void segPre(ll l, ll h, ll in) {  ll segTree[3*mx];   if ( l == h ){  segTree[ in ] = arr[ l ];   return;  }   ll m = (l + h) / 2; segPre(l, m, 2*in);  segPre(m+1, h, 2*in+1);    segTree[ in ] = segTree[ in*2 ]  segTree[ in*2+1 ];   segTree[ in ] = segTree[ in*2 ] ^ segTree[ in*2+1 ];    }
// head collected
// Don't use variable name as --> prev, time, _t, w, y1
// Don't use ceil and pow function

/*** Code Starts from here ***/
//-----------------------------

ll n,m,dp[100005],vis[100005],mxx,u,v,indeg[100005];
vector<ll>adj[100005];
vector<ll>st,st2;

/*void dfs(ll u)
{
    for(vector<ll>::iterator it = adj[u].begin();it!=adj[u].end();it++)
    {
        dp[*it]=max(dp[u]+1,dp[*it]);vis[*it]=1;
        mxx=max(mxx,dp[*it]);
        //cout<< "it : "<< *it << "dp[it] : " << dp[*it] << "\n";
        dfs(*it);
    }
}

void solve()
{
    mxx=0;
    for(int i=1;i<=n;i++)
    {
        dp[i]=0;
        if(!vis[i])
        {
            dfs(i);

        }
    }
    /*for(int i=1;i<=n;i++)
    {
        cous(dp[i]);

    }
    coul(mxx);
}*/

void topo(ll u)
{
    vis[u]=1;
    for(vector<ll>::iterator it = adj[u].begin();it!=adj[u].end();it++)
    {
        if(!vis[*it])
        {
            vis[*it]=1;
            topo(*it);
        }
    }
    st2.pb(u);
}

void fu()
{
    mxx=0;
    for(int i=0;i<st2.size();i++)
    {
        for(vector<ll>::iterator it = adj[st2[i]].begin();it!=adj[st2[i]].end();it++)
        {
            dp[*it] = max(dp[*it],1+dp[st2[i]]);
            mxx=max(mxx,dp[*it]);
        }
    }
    coul(mxx);
}

int main()
{
    cin>>n>>m;
    for(int i=0;i<m;i++)
    {
        cin>>u>>v;
        //indeg[v]++;
        adj[u].pb(v);
    }

    for(ll i=1;i<=n;i++)
    {
        if(!vis[i])
        {
            topo(i);
        }
    }
    reverse(st2.begin(),st2.end());
    //solve();
    fu();
    return 0;
}

/*
4 5
1 2
1 3
3 2
2 4
3 4

6 3
2 3
4 5
5 6

5 8
5 3
2 3
2 4
5 2
5 1
1 4
4 3
1 3

5 6
1 2
1 4
2 3
4 3
3 5
4 2

\

*/


Measured memory_bytes: 13064