// Slower C++ solution:
#include <bits/stdc++.h> 



using namespace std;

 

typedef long long ll;

typedef long double ld;

typedef unsigned long long ull;

 

#define nl '\n'

 

#define y1 aza_ibagaliev

 

#define f first

#define s second

	

#define ed end()

#define bg begin()

#define rbg rbegin()

 

#define rv reverse

#define mp make_pair

#define pb push_back

#define ppb pop_back

#define ppf pop_front

 

#define sz size()

#define all(x) x.bg, x.ed

 

#define pll pair < ll, ll >

#define pii pair < int, int >

 

#define sqr(x) ((x) * 1ll * (x))

#define sqrd(x) ((x) * 1.0 * (x))

 

#define speed ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0)

 

#define rnl cout << "----------------------------------------" << nl

 

#define bit __builtin_popcount

 

inline ll bip(ll x, ll n, ll mod){ll res=1;while(n){if(n & 1){res=(res*x)%mod;}x=(x*x)%mod;n>>=1;}return res;}

        	

const int ppr = 257;

const ll INF = 2e18;

const int inf = 2e9;

const int mod = 1e9 + 7;

const int N = 1e5 + 123;

const ld pi = 3.1741592653589793238462643;

 

const int dx[] = {1, 0, -1, 0};

const int dy[] = {0, 1, 0, -1};



int n, m, dp[N], ans, cnt[N], gr[N];

vector<int>g[N],ord;

bool u[N];



void top(int v) {

	u[v] = 1;

	for(int to : g[v]) 

		if(!u[to]) top(to);

	ord.pb(v);

}



void dfs(int v) {

	u[v] = 1;

	for(int to : g[v])

		if(!u[to]) dfs(to);

}



main() {             	

//  freopen(".in", "r", stdin);

//  freopen(".out", "w", stdout);



//	srand(time(NULL));



//	speed;



	scanf("%d%d", &n, &m);



	while(m--) {

		int x, y;

		scanf("%d%d", &x, &y);

		g[x].pb(y);

		gr[y]++;

	}



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

		if(!u[i]) top(i);

            

	rv(all(ord));



	queue<int>q;



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

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



	while(!q.empty()) {

		int v = q.front();

		q.pop();



		ans = max(ans, dp[v]);



		for(int to : g[v]) {

			dp[to] = max(dp[to], dp[v] + 1);

			cnt[to]++;

			if(cnt[to] == gr[to]) q.push(to);

		}

	}



	cout << ans;



    return 0;                                        

}


// Faster C++ solution for the same problem (measured speedup: 3.490171335118213x):
#define _CRT_SECURE_NO_WARNINGS

/*                   وتزودوا فإن خير الزاد التقوى                    */

/*       وما تدري نفس ماذا تکسب غدا وما تدري نفس باي ارض تموت      */

#include <bits/stdc++.h>

#include<unordered_map>

#include<iomanip>

#include<fstream>

using namespace std;

#define endl '\n'

#define ll long long

#define ull unsigned long long

#define dll double

#define PI acos(-1)

#define watch(x) cout<<#x<<" = "<<x<<" \n"

#define sz(n) n.size()

#define M_Sayed fast() 

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

#define allr(v) v.rbegin(),v.rend()

#define RT(v) return cout<<v,0

#define MP					make_pair

int dx[] = { 0, 1, 0, -1, 1, 1, -1, -1 };

int dy[] = { 1, 0, -1, 0, 1, -1, 1, -1 };

const double EPS = (1e-7);

const ll  mod = (1e9 + 7), OO = 1e9;

ll Ceil(ll x, ll y) { return (x + y - 1) / y; }

void run() {

#ifndef ONLINE_JUDGE

	freopen("input.txt", "r", stdin);

	//freopen("output.txt", "w", stdout);

#else

	//freopen("input", "r", stdin);

	//freopen("output", "w", stdout);

#endif

}

void fast() { ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); }

// BFS (lenth && all path from an start node

vector<vector<ll>>adjList;

ll  vis[100005];

ll  y;

ll ca = 0, x;

ll dfs(int u) {

	if (vis[u])return vis[u];

	for (auto e : adjList[u])

		vis[u] = max(vis[u], 1 + dfs(e));

	return vis[u];

}

int main()

{

	M_Sayed;

	//run();

	int n, e,k;

	cin >> n >> e;

	adjList.resize(n + 1);

	for (int i = 0; i < e; i++) {

		int from, to;

		cin >> from >> to;

		adjList[from].push_back(to);

	}

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

		y = max(y, dfs(i));

	}

	//cout << round(12.3);

	RT(y);

}