// Slower C++ solution:
#include<iostream>

#include<algorithm>

#include<iomanip>

#include<cmath>

#include<vector>

#include<queue>

#include<stack>

#include<set>

#include <cstdio>

#include<map>

#include<string>

#include<assert.h>

#include<unordered_map>

#include <cstring>//memset();

#define Amr_Abdelazim ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);

#define pb push_back

#define pp pop_back

#define ll long long

#define ld long double

#define pll pair<ll,ll> 

#define vll vector<ll> 

#define vvll vector<vector<ll> >  

#define vpll vector<pair<ll,ll> > 

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

#define rep(i,n)   for(int i=0;i<n;i++)

#define repp(s,i,n)   for(int i=s;i<n;i++)

#define print(v) for(auto i:v)cout<<i<<" ";cout<<"\n"; 

#define mkp make_pair

#define clr(ar,v) memset(ar,v,sizeof(ar));

#define TC ll t;cin>>t;while(t--)

#define in_vec ll n;cin>>n;vll v(n);rep(i,n)cin >> v[i];

#define EPS 1e-9

using namespace std;

const int mod = 1000000007;

const int N = 1000005;

class cmp{

public:

	bool operator() (pair<ll, pll> &A, pair<ll, pll> &B){

		return A > B;

	}

};

bool by_sec(pll &A, pll &B){

	return A.second < B.second;

}

bool is(pll a, pll b){

	return !((a.first > b.second&&a.second > b.second) || (a.first < b.first&&a.second < b.first));

}

ld dist(pll p1, pll p2){

	return (ld)sqrt((ld)(p1.first - p2.first)*(p1.first - p2.first) + (ld)(p1.second - p2.second)*(p1.second - p2.second));

}

vvll vv(100000+9);

ll dp[100000 + 9];

ll path(ll n){

	if (vv[n].size() == 0)return 0;

	if (dp[n] == -1){

		ll mx = -1;

		rep(i, vv[n].size())mx = max(mx, path(vv[n][i])+1);

		dp[n] = mx;

	}

	return dp[n];

}

int main()

{

	Amr_Abdelazim

		clr(dp, -1);

		ll n, m,ans=0;

	cin >> n >> m;

	while (m--){

		ll a, b;

		cin >> a >> b;

		vv[a].push_back(b);

	}

	repp(1, i, n + 1)

		ans = max(ans, path(i));

	cout << ans << "\n";

	return 0;

}

// Faster C++ solution for the same problem (measured speedup: 1.2736320342492424x):
#pragma region

#include <algorithm>

#include <cstring>

#include <iostream>

#include <map>

#include <queue>

#include <stack>

#include <string>

#include <vector>

typedef long long ll;

#define tr t[root]

#define lson t[root << 1]

#define rson t[root << 1 | 1]

#define rep(i, a, n) for (long long i = a; i <= n; ++i)

#define per(i, a, n) for (long long i = n; i >= a; --i)

#define IO ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)

template <typename T>

void read(T &x) {

    x = 0;

    char ch = getchar();

    ll f = 1;

    while (!isdigit(ch)) {

        if (ch == '-') f *= -1;

        ch = getchar();

    }

    while (isdigit(ch)) {

        x = x * 10 + ch - 48;

        ch = getchar();

    }

    x *= f;

}

using namespace std;

/*

 *                                                     __----~~~~~~~~~~~------___

 *                                    .  .   ~~//====......          __--~ ~~

 *                    -.            \_|//     |||\\  ~~~~~~::::... /~

 *                 ___-==_       _-~o~  \/    |||  \\            _/~~-

 *         __---~~~.==~||\=_    -_--~/_-~|-   |\\   \\        _/~

 *     _-~~     .=~    |  \\-_    '-~7  /-   /  ||    \      /

 *   .~       .~       |   \\ -_    /  /-   /   ||      \   /

 *  /  ____  /         |     \\ ~-_/  /|- _/   .||       \ /

 *  |~~    ~~|--~~~~--_ \     ~==-/   | \~--===~~        .\

 *           '         ~-|      /|    |-~\~~       __--~~

 *                       |-~~-_/ |    |   ~\_   _-~            /\

 *                            /  \     \__   \/~                \__

 *                        _--~ _/ | .-~~____--~-/                  ~~==.

 *                       ((->/~   '.|||' -_|    ~~-/ ,              . _||

 *                                  -_     ~\      ~~---l__i__i__i--~~_/

 *                                  _-~-__   ~)  \--______________--~~

 *                                //.-~~~-~_--~- |-------~~~~~~~~

 *                                       //.-~~~--\

 *                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 */



#pragma endregion

const int maxn = 1e5 + 5;

int n, m;

vector<int> g[maxn];

int dp[maxn], in[maxn];

int main() {

    IO;

    cin >> n >> m;

    while (m--) {

        int x, y;

        cin >> x >> y;

        g[x].push_back(y);

        in[y]++;

    }

    queue<int> q;

    rep(i, 1, n) if (!in[i]) q.push(i);

    int ans = 0, sz = q.size();

    while (q.size()) {

        int now = q.front();

        q.pop();

        for (auto nex : g[now]) {

            in[nex]--;

            if (!in[nex])

                q.push(nex);

        }

        --sz;

        if (!sz) {

            sz = q.size();

            ans++;

        }

    }

    cout << ans - 1 << endl;

}