#include<iostream>
#include<bits/stdc++.h>
#include<vector>
#include<cmath>
#include<set>
#include<utility>
#include<algorithm>
#include<functional>
using namespace std;
typedef long long ull;
typedef pair<ull,ull> p;
#define mp make_pair
#define append push_back
vector<ull>v;
set<ull>s;
multiset<ull>ms;
ull prime[10000000];
#define f(i,a,b) for(int i=a;i<(b);i++)
#define print cout<< 
void boost() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
}

vector<ull>visited(10000000,0);
vector<ull>adj[100001];

struct node {
    ull data;
    node *left;
    node *right;
};
 
node *getNode(ull val) {
    node *newNode = new node();
    newNode->data = val;
    newNode->left = newNode->right = NULL;
    return newNode;
}
 
 
node *findNode(node *root, ull data) {
    if (root->data == data) 
        return root;
    if (root->left) findNode(root->left, data);
    if (root->right) findNode(root->right, data);
}
 
void display(node *root) {
    // displaying the tree
    queue<node*> Q;
    Q.push(root);
    while (!Q.empty()) {
        node *x = Q.front();
        Q.pop();
        if (x->left) Q.push(x->left);
        if (x->right) Q.push(x->right);
        cout << x->data << " ";
    }
    cout << endl;
}
 
node *copy(node *root) {
    if (!root) 
        return root;
    node *temp = new node();
    temp->data = root->data;
    temp->left = copy(root->left);
    temp->right = copy(root->right);
    return temp;
}
 
void mirror(node *root) {
    if (root) {
        mirror(root->left);
        mirror(root->right);
        node *temp = root->left;
        root->left = root->right;
        root->right = temp;
    }
    return;
}
 
int findMirror(int target, node *left, node *right) {
    if (left == NULL || right == NULL) return 0;
    if (left->data == target) return right->data;
    if (right->data == target) return left->data;
    int mirrorValue = findMirror(target, left->left, right->right);
    if (mirrorValue) return mirrorValue;
    return findMirror(target, left->right, right->left);
}

ull ncrmodp(ull num,ull r,ull mod)
{
    ull C[r+1];
    ull i,j;
    memset(C,0,sizeof(C));
    C[0]=1;
    for(i=1;i<=num;i++)
    {
        for(j=min(i,r);j>0;j--)
        {
            C[j]=((C[j])%mod+(C[j-1])%mod)%mod;
        }
    }
    return C[r];
} 

ull multiply(ull n,ull m)
{
    
    ull prod=1;
    f(i,0,n)
    {
        prod*=v[i];
        prod=prod%m;
    }
    return prod;
}

ull gcd(ull a, ull b) { return b == 0 ? a : gcd(b, a % b); }

ull power(ull x,ull y,ull p)
{
    ull res = 1;     
    x = x % p; 
 
    while (y > 0)
    {
        if (y & 1)
            res = (res*x) % p;
 
        y = y>>1; // y = y/2
        x = (x*x) % p;  
    }
    return res;
}

ull dp[100001];
void dfs(ull k) 
{
    visited[k] = 1;
    for(int i = 0;i < adj[k].size();++i)   
    {
        if(visited[adj[k][i]] == 0)
        {
           dfs(adj[k][i]);
        }
        dp[k]=max(dp[k],1+dp[adj[k][i]]);
    }
}

void sieve(ull ending)
{
    for(int i=2;i<ending;i++)
        prime[i]=1;
    for(int i=2;i*i<=ending;i++)
    {
        if(prime[i]==1)
            {
                for(int j=2*i;j<=ending;j=j+i)
                {
                    prime[j]=0;
                }
            }
    }
    prime[1]=0;
}

int main()
{
    boost();
    ull i,j;
    ull t,n,m;
    cin>>n>>m;
    for(i=0;i<m;i++)
    {
        ull a,b;
        cin>>a>>b;
        adj[a].push_back(b);
    }
    ull ma=-1;
    for(i=1;i<=n;i++)
    {
        if(!visited[i])
        dfs(i);
    }
    for(i=1;i<=n;i++)
    {
        ma=max(ma,dp[i]);
    }
    cout<<ma<<endl;
return 0;
}


Measured memory_bytes: 87680