#include <algorithm>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <map>
#include <set>
using namespace std;

#define FOR(i, l, r)  for (int(i) = int(l); int(i) <= int(r); ++i)
#define FORD(i, r, l) for (int(i) = int(r); int(i) >= int(l); --i)
#define hashmap unordered_map
#define hashset unordered_set
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define itr iterator
#define rtr reverse_iterator

enum color_t {White, Black, Gray};
typedef double          db;
typedef long long       ll;     typedef unsigned long long  ull;
typedef pair<int, int>  pi;     typedef pair<ll, ll>    pll;
typedef map<int, int>   mi;     typedef map<ll, ll>     mll;
typedef set<int>        si;     typedef vector<si>      vsi;
typedef set<ll>         sll;    typedef vector<sll>     vsll;
typedef set<pi>         spi;    typedef vector<spi>     vspi;
typedef set<pll>        spll;   typedef vector<spll>    vspll;
typedef vector<color_t> ve;     typedef vector<ve>      vme;
typedef vector<string>  vs;     typedef vector<vs>      vms;
typedef vector<bool>    vb;     typedef vector<vb>      vmb;
typedef vector<char>    vc;     typedef vector<vc>      vmc;
typedef vector<int>     vi;     typedef vector<vi>      vmi;    
typedef vector<ll>      vll;    typedef vector<vll>     vmll;
typedef vector<pi>      vpi;    typedef vector<vpi>     vmpi;
typedef vector<pll>     vpll;   typedef vector<vpll>    vmpll;

inline int readInt()       {char c;while(c=getchar(),c!='-'&&(c<'0'||c>'9'));bool sign=(c=='-');if(sign)c=getchar();int n=c-'0';while(c=getchar(),c>='0'&&c<='9')n=10*n+c-'0';return(!sign)?n:-n;}
inline ll readLong()       {char c;while(c=getchar(),c!='-'&&(c<'0'||c>'9'));bool sign=(c=='-');if(sign)c=getchar();ll  n=c-'0';while(c=getchar(),c>='0'&&c<='9')n=10*n+c-'0';return(!sign)?n:-n;}
inline void getInt(int& n) {char c;while(c=getchar(),c!='-'&&(c<'0'||c>'9'));bool sign=(c=='-');if(sign)c=getchar();    n=c-'0';while(c=getchar(),c>='0'&&c<='9')n=10*n+c-'0';      if(sign)n=-n;}
inline void getLong(ll& n) {char c;while(c=getchar(),c!='-'&&(c<'0'||c>'9'));bool sign=(c=='-');if(sign)c=getchar();    n=c-'0';while(c=getchar(),c>='0'&&c<='9')n=10*n+c-'0';      if(sign)n=-n;}
inline string readString() {char c;while(c=getchar(),c==' '||c=='\n'||c=='\t');string s({c});while(c=getchar(),c!=EOF&&c!=' '&&c!='\n'&&c!='\t')s+=c;return s;}
char bufWrite[20];
template<typename T>inline void writeInt(T x)               {if(x<0)putchar('-'),x=-x;char*bufPos=bufWrite;do{*bufPos++=x%10+'0';}while(x/=10);do{putchar(*--bufPos);}while(bufPos>bufWrite);}
template<typename T>inline void printInt(T x, char c = EOF) {if(x<0)putchar('-'),x=-x;char*bufPos=bufWrite;do{*bufPos++=x%10+'0';}while(x/=10);do{putchar(*--bufPos);}while(bufPos>bufWrite);if(c!=EOF)putchar(c);}
template<typename T>inline T gcd(T a,T b){while(b!=0)swap(b,a%=b);return a;}
template<typename T>inline T lcm(T a,T b){return a/gcd(a,b)*b;}
template<typename T>inline tuple<T,T,T>extgcd(T a,T b){if(!a)return mt(b,0,1);T g,x,y;tie(g,x,y)=extgcd(b%a,a);return mt(g,y-(b/a)*x,x);}
template <class T> T    bitGet    (T  x, int bit)           { return T(1) & (x >> (bit - 1)); }
template <class T> void bitSet    (T &x, int bit)           { x |=  (T(1) << (bit - 1)); }
template <class T> void bitReset  (T &x, int bit)           { x &= ~(T(1) << (bit - 1)); }
template <class T> void bitFlip   (T &x, int bit)           { x ^=  (T(1) << (bit - 1)); }
template <class T> void bitMake   (T &x, int bit, bool val) { x ^=  (T(1) << (bit - 1)) & (-val ^ x); }
// ======================================================================
/// ======================================================================
// const db oo = 0.1 / 0; /// inf
const ll LINF = (1LL << 60); /// 1e18
const int INF = (1 << 30); /// 1e9
const int LIM = (1 << 24); /// 1e7
const int MOD = 1e9 + 7;
const int BASE = 1e4;
const int DIGIT = 4;


/// ======================================================================


int n, m, k;
vmi G; /// Weighted   Graph

vb mark; /// Graph
ve color; /// Graph
vi dep, deg, par; /// Tree: Depth - Degree - Parent
vi lvl, cap, ori; /// DSU:  Level - Capacity - Origin

inline void DSU_make(int u) { ori[u] = -1; cap[u] = 1; lvl[u] = 1; }
inline int DSU_find(int u) { return ori[u] < 0 ? u : (ori[u] = DSU_find(ori[u])); }
inline void DSU_union(int u, int v)
{
    u = DSU_find(u), v = DSU_find(v);
    if (u == v) return ;

    if (lvl[u] < lvl[v]) swap(u, v);
    ori[v] = u;
    cap[u] += cap[v];
    lvl[u] += (lvl[u] == lvl[v]);
}

vi f;
int dfs(int u)
{
    if (f[u] != -1) return f[u];
    f[u] = 0;

    for (int v : G[u])
        f[u] = max(f[u], dfs(v) + 1);
    
    return f[u];
}

int readGraph()
{
    n = readInt();
    m = readInt();

    G.resize(n + 1);
    f.assign(n + 1, -1);
    mark.assign(n + 1, false);
    // color.assign(n + 1, White);
    // dep.assign(n + 1, 0); deg.assign(n + 1, 0); par.assign(n + 1, -1);
    // cap.assign(n + 1, 1); lvl.assign(n + 1, 1); ori.assign(n + 1, -1);
    for (int i = 0; i < m; ++i)
    {
        int u = readInt();
        int v = readInt();
        G[u].push_back(v); 
        // G[v].push_back(u);
        
        // int c = readInt();
        // G[u].push_back({v, c});
        // G[u].push_back({u, c});

        // deg[u]++; deg[v]++;
        // DSU_union(u, v);
    }



    return 0;
}

int main()
{
    readGraph();

    int res = 1;
    for (int u = 1; u <= n; ++u)
        res = max(res, dfs(u));
    
    cout << res;
    return 0;
}

Measured memory_bytes: 8192