stablegradients/pie-gem5-pairs huggingface dataset:
// Slower C++ solution:
#include<bits/stdc++.h>

using namespace std;

typedef long long int ll;

const int MAX=1e5 + 10;

int n,m,Sub[MAX];

vector<int>g[MAX];

bool vis[MAX];

int dfs(int root)

{

    if(vis[root])return Sub[root];

    vis[root]=1;

    int ans=0;

    for(int x:g[root]){

            ans=max(ans,1+ dfs(x));

    }

    return Sub[root]=ans;

}

int main ()

{

    cin >> n >> m;

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

        int u,v;

        cin >> u >> v;

        g[u].push_back(v);

    }

    int ans=0;

    for(int i=1;i<=n;i++) if(!vis[i])ans = max(ans,dfs(i));

    cout<<ans;

    return 0;

}


// Faster C++ solution for the same problem (measured speedup: 3.499697996945482x):
#include<cstdio>

#include<cstring>

#include<iostream>

#include<algorithm>

#include<queue>

using namespace std;

const int maxn=100000+10;

struct node

{

	int to,next,w;

}edge[maxn];

int k=1,head[maxn],ind[maxn],n,m,dp[maxn];

void add(int u,int v,int w)

{

	edge[++k].to=v;edge[k].next=head[u];head[u]=k;edge[k].w=w;

}

void Topsort()

{

	queue<int>q;

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

		if(!ind[i])

			q.push(i);

	while(!q.empty())

	{

		int x=q.front();q.pop();

		for(int i=head[x];i;i=edge[i].next)

		{

			dp[edge[i].to]=max(dp[edge[i].to],dp[x]+edge[i].w);

			ind[edge[i].to]--;

			if(!ind[edge[i].to])

				q.push(edge[i].to);

		}

	}

}

int  main()

{

	cin>>n>>m;

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

	{

		int u,v;

		cin>>u>>v;

		add(u,v,1);

		ind[v]++;

	}

	Topsort();

	int ans=0;

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

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

	cout<<ans<<endl;

	return 0;

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

using namespace std;



#define MX 100005

#define ll long long



vector < int > G[MX];

vector < int > topsort;

bool vis[MX];

ll dp[MX];



void dfs(int n){

    vis[n] = 1;

    for (int i = 0; i < G[n].size(); i++){

        int nxt = G[n][i];

        if (!vis[nxt])

            dfs(nxt);

    }

    topsort.push_back(n);

}



void solve(){

    for (int x = 0; x < topsort.size(); x++){

        int cur = topsort[x];

        if (G[cur].size() == 0){

            dp[cur] = 0;

        }

        else{

            ll mx = 0;

            for (int i = 0; i < G[cur].size(); i++){

                int nxt = G[cur][i];

                mx = max(mx, dp[nxt]);

            }

            dp[cur] = mx + 1;

        }

    }





}



int main()

{

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

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

        int u, v; scanf("%d%d", &u, &v);

        G[u].push_back(v);

    }



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

        if (!vis[i])

            dfs(i);

    }

    solve();

    ll res = 0;

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

        res = max(res, dp[i]);



    printf("%lld\n", res);

    return 0;

}




// Faster C++ solution for the same problem (measured speedup: 3.4881995410156166x):
#include<cstdio>

#include<cstring>

#include<iostream>

#include<algorithm>

#include<queue>

using namespace std;

const int maxn=100000+10;

struct node

{

	int to,next,w;

}edge[maxn];

int k=1,head[maxn],ind[maxn],n,m,dp[maxn];

void add(int u,int v,int w)

{

	edge[++k].to=v;edge[k].next=head[u];head[u]=k;edge[k].w=w;

}

void Topsort()

{

	queue<int>q;

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

		if(!ind[i])

			q.push(i);

	while(!q.empty())

	{

		int x=q.front();q.pop();

		for(int i=head[x];i;i=edge[i].next)

		{

			dp[edge[i].to]=max(dp[edge[i].to],dp[x]+edge[i].w);

			ind[edge[i].to]--;

			if(!ind[edge[i].to])

				q.push(edge[i].to);

		}

	}

}

int  main()

{

	cin>>n>>m;

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

	{

		int u,v;

		cin>>u>>v;

		add(u,v,1);

		ind[v]++;

	}

	Topsort();

	int ans=0;

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

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

	cout<<ans<<endl;

	return 0;

}
// Slower C++ solution:
// PUJI TUHAN !!! YES

#include<iostream>

#include<queue>

#include<vector>

#define ii pair<int,int>

#define iii pair<int,ii> 

using namespace std;

int v,e,a,b;

vector<int> adjl[110000];

int vis[110000];

int memo[110000];

int start = 0;

int dp(int nodes){

//	cout<<nodes<<"\n";

	int sz = adjl[nodes].size();

	if(sz == 0) return 0;

	if(memo[nodes]!=-1) return memo[nodes];

	int ret = 0;

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

//		cout<<" visit "<<adjl[nodes][i]<<"\n";

		ret = max(ret, dp(adjl[nodes][i]) + 1);

	}

//	cout<<"\n";

	return memo[nodes] = ret;

}





int main(){

	cin>>v>>e;

	for(int i = 1;i<=v;i++) adjl[0].push_back(i);

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

		cin>>a>>b;

		adjl[a].push_back(b);

	}

	int ans = 0;

	for(int i = 0;i<=v;i++) memo[i] = -1;

	ans = dp(0) -1 ;

	cout<<ans<<"\n";

//	for(int i = 0;i<=v;i++) cout<<memo[i]<<" ";cout<<"\n";

//	for(int i = 0;i<=v;i++) ans = max(ans,)

	return 0;

}

// Faster C++ solution for the same problem (measured speedup: 3.758658022806908x):
#include<cstdio>

#include<cstring>

#include<iostream>

#include<algorithm>

#include<queue>

using namespace std;

const int maxn=100000+10;

struct node

{

	int to,next,w;

}edge[maxn];

int k=1,head[maxn],ind[maxn],n,m,dp[maxn];

void add(int u,int v,int w)

{

	edge[++k].to=v;edge[k].next=head[u];head[u]=k;edge[k].w=w;

}

void Topsort()

{

	queue<int>q;

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

		if(!ind[i])

			q.push(i);

	while(!q.empty())

	{

		int x=q.front();q.pop();

		for(int i=head[x];i;i=edge[i].next)

		{

			dp[edge[i].to]=max(dp[edge[i].to],dp[x]+edge[i].w);

			ind[edge[i].to]--;

			if(!ind[edge[i].to])

				q.push(edge[i].to);

		}

	}

}

int  main()

{

	cin>>n>>m;

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

	{

		int u,v;

		cin>>u>>v;

		add(u,v,1);

		ind[v]++;

	}

	Topsort();

	int ans=0;

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

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

	cout<<ans<<endl;

	return 0;

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

using namespace std;

int ans,n,m,a[100010],b[100010],dp[100010];

vector < int > adj[100010];

bool visit[100010];

int dfs(int x)

{

	if(dp[x]!=-1) return dp[x];

	dp[x] = 1;

	for(int i=0;i<adj[x].size();i++)

	{

		dp[x] = max(dp[x],1+dfs(adj[x][i]));

	}

	return dp[x];

}

int main()

{

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

	for(int i=0;i<m;i++)

	{

		scanf("%d %d",&a[i],&b[i]);

		adj[a[i]].push_back(b[i]);

	}

	for(int i=1;i<=n;i++) dp[i] = -1;

	ans = 1;

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

	{

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

	}

	printf("%d\n",ans-1);

	return 0;

}

// Faster C++ solution for the same problem (measured speedup: 3.486256071960989x):
#include<cstdio>

#include<cstring>

#include<iostream>

#include<algorithm>

#include<queue>

using namespace std;

const int maxn=100000+10;

struct node

{

	int to,next,w;

}edge[maxn];

int k=1,head[maxn],ind[maxn],n,m,dp[maxn];

void add(int u,int v,int w)

{

	edge[++k].to=v;edge[k].next=head[u];head[u]=k;edge[k].w=w;

}

void Topsort()

{

	queue<int>q;

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

		if(!ind[i])

			q.push(i);

	while(!q.empty())

	{

		int x=q.front();q.pop();

		for(int i=head[x];i;i=edge[i].next)

		{

			dp[edge[i].to]=max(dp[edge[i].to],dp[x]+edge[i].w);

			ind[edge[i].to]--;

			if(!ind[edge[i].to])

				q.push(edge[i].to);

		}

	}

}

int  main()

{

	cin>>n>>m;

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

	{

		int u,v;

		cin>>u>>v;

		add(u,v,1);

		ind[v]++;

	}

	Topsort();

	int ans=0;

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

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

	cout<<ans<<endl;

	return 0;

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

using namespace std;

#define db(x) cerr<<__LINE__<<": "<<#x<<" = "<<(x)<<'\n'

const int N = 1e5;

vector<int> adj[N+9];

int vis[N+9], mxdist[N+9];



int dfs(int r) {

	if(vis[r]) return mxdist[r];

	vis[r]=1;

	int res=0;

	for(int x: adj[r]) {

		res=max(res, dfs(x)+1);

	}

	return mxdist[r] = res;

}

int main(){

	ios_base::sync_with_stdio(0);

	int a,b,n,m,T,cas=0;

	cin>>n>>m;

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

		cin>>a>>b;

		adj[a].emplace_back(b);

	}

	int res=0;

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

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

	}

	cout<<res<<endl;

	return 0;

}

// Faster C++ solution for the same problem (measured speedup: 3.5209823926884876x):
#include<cstdio>

#include<cstring>

#include<iostream>

#include<algorithm>

#include<queue>

using namespace std;

const int maxn=100000+10;

struct node

{

	int to,next,w;

}edge[maxn];

int k=1,head[maxn],ind[maxn],n,m,dp[maxn];

void add(int u,int v,int w)

{

	edge[++k].to=v;edge[k].next=head[u];head[u]=k;edge[k].w=w;

}

void Topsort()

{

	queue<int>q;

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

		if(!ind[i])

			q.push(i);

	while(!q.empty())

	{

		int x=q.front();q.pop();

		for(int i=head[x];i;i=edge[i].next)

		{

			dp[edge[i].to]=max(dp[edge[i].to],dp[x]+edge[i].w);

			ind[edge[i].to]--;

			if(!ind[edge[i].to])

				q.push(edge[i].to);

		}

	}

}

int  main()

{

	cin>>n>>m;

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

	{

		int u,v;

		cin>>u>>v;

		add(u,v,1);

		ind[v]++;

	}

	Topsort();

	int ans=0;

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

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

	cout<<ans<<endl;

	return 0;

}
// 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.502602855058526x):
#include<cstdio>

#include<cstring>

#include<iostream>

#include<algorithm>

#include<queue>

using namespace std;

const int maxn=100000+10;

struct node

{

	int to,next,w;

}edge[maxn];

int k=1,head[maxn],ind[maxn],n,m,dp[maxn];

void add(int u,int v,int w)

{

	edge[++k].to=v;edge[k].next=head[u];head[u]=k;edge[k].w=w;

}

void Topsort()

{

	queue<int>q;

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

		if(!ind[i])

			q.push(i);

	while(!q.empty())

	{

		int x=q.front();q.pop();

		for(int i=head[x];i;i=edge[i].next)

		{

			dp[edge[i].to]=max(dp[edge[i].to],dp[x]+edge[i].w);

			ind[edge[i].to]--;

			if(!ind[edge[i].to])

				q.push(edge[i].to);

		}

	}

}

int  main()

{

	cin>>n>>m;

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

	{

		int u,v;

		cin>>u>>v;

		add(u,v,1);

		ind[v]++;

	}

	Topsort();

	int ans=0;

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

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

	cout<<ans<<endl;

	return 0;

}
// Slower C++ solution:
#include<cstdio>

#include<iostream>

#include<cstring>

#include<algorithm>

#include<vector>

#include<queue>



using namespace std;

const int maxn = 1e5 + 5;



vector<int>vc[maxn];

queue<int> que;



int in[maxn], sum[maxn];

int n, m, ans;





int main(){

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

	int u, v;

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

		scanf("%d %d", &u, &v); //u -> v

		vc[u].push_back(v);

		in[v]++;

	}

	int p = 0;

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

		if(!in[i]) 

			que.push(i);

	}

	int x;

	while(!que.empty()){

		x = que.front();

		que.pop();

		int len = vc[x].size();

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

			int y = vc[x][i];

			in[y]--;

			if(!in[y]) {

				que.push(y);

				sum[y] = sum[x] + 1;

			}

		}

	}

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

		ans = max(ans, sum[i]);

	}

	printf("%d\n" ,ans);

}

// Faster C++ solution for the same problem (measured speedup: 3.4946456829879846x):
#include<cstdio>

#include<cstring>

#include<iostream>

#include<algorithm>

#include<queue>

using namespace std;

const int maxn=100000+10;

struct node

{

	int to,next,w;

}edge[maxn];

int k=1,head[maxn],ind[maxn],n,m,dp[maxn];

void add(int u,int v,int w)

{

	edge[++k].to=v;edge[k].next=head[u];head[u]=k;edge[k].w=w;

}

void Topsort()

{

	queue<int>q;

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

		if(!ind[i])

			q.push(i);

	while(!q.empty())

	{

		int x=q.front();q.pop();

		for(int i=head[x];i;i=edge[i].next)

		{

			dp[edge[i].to]=max(dp[edge[i].to],dp[x]+edge[i].w);

			ind[edge[i].to]--;

			if(!ind[edge[i].to])

				q.push(edge[i].to);

		}

	}

}

int  main()

{

	cin>>n>>m;

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

	{

		int u,v;

		cin>>u>>v;

		add(u,v,1);

		ind[v]++;

	}

	Topsort();

	int ans=0;

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

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

	cout<<ans<<endl;

	return 0;

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

using namespace std;



#define ll long long

#define pb push_back

#define mp make_pair

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

#define f first

#define se second

#define lb lower_bound

#define ub upper_bound

#define pii pair<int, int>

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



const int N = 1e5 + 144, mod = 1e9 + 7, inf = 1e9 + 7;

int n, m, dp[N];

vector <int> g[N];

bool was[N];



ll bp(ll x, ll y){

    if(y == 0)

        return 1;

    if(y & 1)

        return (x * bp(x, y - 1));

    ll z = bp(x, y / 2);

    return (z * z) % mod;

}



void dfs(int x){

    was[x] = true;

    for(auto to: g[x]){

        if(!was[to])

            dfs(to);

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

    }

}



int main(){

    boost;

    cin >> n >> m;

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

        int x, y;

        cin >> x >> y;

        g[x].pb(y);

    }

    int ans = 0;

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

        if(!was[i])

            dfs(i);

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

    }

    cout << ans;

    return 0;

}




// Faster C++ solution for the same problem (measured speedup: 3.521733544398429x):
#include<cstdio>

#include<cstring>

#include<iostream>

#include<algorithm>

#include<queue>

using namespace std;

const int maxn=100000+10;

struct node

{

	int to,next,w;

}edge[maxn];

int k=1,head[maxn],ind[maxn],n,m,dp[maxn];

void add(int u,int v,int w)

{

	edge[++k].to=v;edge[k].next=head[u];head[u]=k;edge[k].w=w;

}

void Topsort()

{

	queue<int>q;

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

		if(!ind[i])

			q.push(i);

	while(!q.empty())

	{

		int x=q.front();q.pop();

		for(int i=head[x];i;i=edge[i].next)

		{

			dp[edge[i].to]=max(dp[edge[i].to],dp[x]+edge[i].w);

			ind[edge[i].to]--;

			if(!ind[edge[i].to])

				q.push(edge[i].to);

		}

	}

}

int  main()

{

	cin>>n>>m;

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

	{

		int u,v;

		cin>>u>>v;

		add(u,v,1);

		ind[v]++;

	}

	Topsort();

	int ans=0;

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

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

	cout<<ans<<endl;

	return 0;

}
// Slower C++ solution:
//بِسْمِ اللَّهِ الرَّحْمَنِ الرَّحِيمِ

//لا إله إلا الله محمد رسول الله



#include <bits/stdc++.h>



#pragma GCC optimize("Ofast")



#define ll long long

#define pb push_back

#define fr first

#define sc second

#define in freopen("input.txt", "r" , stdin)

#define out freopen("snakes.out", "w", stdout)

using namespace std;



vector <ll> g[100005];

vector<ll> ans;

ll n , m;

ll d[100005];

bool used[100005];

bool used1[100005];

ll an = 0;

void dfs1 (ll v) {

    used1[v] = 1;

    for (int i = 0; i < g[v].size();i++) {

        ll to = g[v][i];

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

        if (!used1[to])

            dfs1 (to);

    }

}

void dfs (ll v) {

    used[v] = 1;

    for (int i = 0; i < g[v].size(); i++) {

        ll to = g[v][i];

        if (!used[to]) {

            dfs (to);

        }

    }

    ans.pb (v);

}



int main(){

    //in;

    //out;

    cin >> n >> m;

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

        ll a , b;

        cin >> a >> b;

        g[a].pb (b);

    }





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

        if (!used[i]) {

            dfs (i);

        }

    }



    reverse(ans.begin(), ans.end());



    for (int i = 0; i < ans.size(); i++) {

            dfs1 (ans[i]);

    }



    for (int i = 1; i <= n; i++) an = max (an, d[i]);



    cout << an;

}




// Faster C++ solution for the same problem (measured speedup: 3.500974880349667x):
#include<cstdio>

#include<cstring>

#include<iostream>

#include<algorithm>

#include<queue>

using namespace std;

const int maxn=100000+10;

struct node

{

	int to,next,w;

}edge[maxn];

int k=1,head[maxn],ind[maxn],n,m,dp[maxn];

void add(int u,int v,int w)

{

	edge[++k].to=v;edge[k].next=head[u];head[u]=k;edge[k].w=w;

}

void Topsort()

{

	queue<int>q;

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

		if(!ind[i])

			q.push(i);

	while(!q.empty())

	{

		int x=q.front();q.pop();

		for(int i=head[x];i;i=edge[i].next)

		{

			dp[edge[i].to]=max(dp[edge[i].to],dp[x]+edge[i].w);

			ind[edge[i].to]--;

			if(!ind[edge[i].to])

				q.push(edge[i].to);

		}

	}

}

int  main()

{

	cin>>n>>m;

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

	{

		int u,v;

		cin>>u>>v;

		add(u,v,1);

		ind[v]++;

	}

	Topsort();

	int ans=0;

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

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

	cout<<ans<<endl;

	return 0;

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

#define F first

#define S second

#define T second.first

#define C second.second

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

using namespace std;

typedef long long ll;

typedef pair<int, int> pii;

typedef pair<int,pair<int,int>> piii;



const int N= 1e2+5, L = 14, OO = 0x3f3f3f3f;

const int M= 1e9+7;

const double ESP = 1e-8;



int n,m, u,v;

vector<int>adj[100005];

int dp[100005];



int solve(int u){

    int& ret = dp[u];

    if(~ret)return ret;



    ret = 0;

    for(int v: adj[u])

        ret = max(ret, solve(v)+1);



    return ret;

}



int main(){

    FIO

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

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

    cin>>n>>m;

    memset(dp, -1, sizeof dp);

    while(m--){

        cin>>u>>v;

        adj[u].push_back(v);

    }

    int ans = 0;

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

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

    }

    cout<<ans;

}


// Faster C++ solution for the same problem (measured speedup: 3.9211553573147877x):
#include<cstdio>

#include<cstring>

#include<iostream>

#include<algorithm>

#include<queue>

using namespace std;

const int maxn=100000+10;

struct node

{

	int to,next,w;

}edge[maxn];

int k=1,head[maxn],ind[maxn],n,m,dp[maxn];

void add(int u,int v,int w)

{

	edge[++k].to=v;edge[k].next=head[u];head[u]=k;edge[k].w=w;

}

void Topsort()

{

	queue<int>q;

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

		if(!ind[i])

			q.push(i);

	while(!q.empty())

	{

		int x=q.front();q.pop();

		for(int i=head[x];i;i=edge[i].next)

		{

			dp[edge[i].to]=max(dp[edge[i].to],dp[x]+edge[i].w);

			ind[edge[i].to]--;

			if(!ind[edge[i].to])

				q.push(edge[i].to);

		}

	}

}

int  main()

{

	cin>>n>>m;

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

	{

		int u,v;

		cin>>u>>v;

		add(u,v,1);

		ind[v]++;

	}

	Topsort();

	int ans=0;

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

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

	cout<<ans<<endl;

	return 0;

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

#include<bits/stdc++.h>



using namespace std;



int n,m;

vector<int>v[200005];

int ans=0,c=0;

int dp[200005];

int vis[200005];

int mx=0;

void dfs(int node){

    vis[node]=1;

    for(int j=0;j<v[node].size();j++){

            if(!vis[v[node][j]])

            dfs(v[node][j]);

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

        mx=max(mx,dp[node]);

    }

    }





int main()

{

    cin>>n>>m;

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

        int x,y;

        cin>>x>>y;

        v[x].push_back(y);

    }

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

    if(!vis[i]){

        dfs(i);

    }

   }

   cout<<mx;



    return 0;

}


// Faster C++ solution for the same problem (measured speedup: 6.404828850185879x):
#include<cstdio>

#include<cstring>

#include<iostream>

#include<algorithm>

#include<queue>

using namespace std;

const int maxn=100000+10;

struct node

{

	int to,next,w;

}edge[maxn];

int k=1,head[maxn],ind[maxn],n,m,dp[maxn];

void add(int u,int v,int w)

{

	edge[++k].to=v;edge[k].next=head[u];head[u]=k;edge[k].w=w;

}

void Topsort()

{

	queue<int>q;

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

		if(!ind[i])

			q.push(i);

	while(!q.empty())

	{

		int x=q.front();q.pop();

		for(int i=head[x];i;i=edge[i].next)

		{

			dp[edge[i].to]=max(dp[edge[i].to],dp[x]+edge[i].w);

			ind[edge[i].to]--;

			if(!ind[edge[i].to])

				q.push(edge[i].to);

		}

	}

}

int  main()

{

	cin>>n>>m;

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

	{

		int u,v;

		cin>>u>>v;

		add(u,v,1);

		ind[v]++;

	}

	Topsort();

	int ans=0;

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

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

	cout<<ans<<endl;

	return 0;

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





using namespace std;

typedef long long ll;

typedef unsigned long long ull;

typedef double dd;

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

#define endl "\n"

#define clr(n, r) memset(n,r,sizeof(n));



void fast() {

    cin.tie(0);

    cin.sync_with_stdio(0);

}



int OO = 100000000,n,m;

int dp[100009];

vector<vector<int>>edges(1e5);

int ans(int i){

    int &ret=dp[i];

    if(~ret)return ret;

    if(i==n+1||edges[i].empty())return 0;

    ret =0;

    for (int j = 0; j <edges[i].size() ; ++j) {

        ret=max (ret,1+ans(edges[i][j]));

    }

    return ret;

}







int main() {

    fast();

    cin>>n>>m;

    clr(dp,-1);

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

        int a,b;cin>>a>>b;

        edges[a].push_back(b);

    }

    int s=0;

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

     s=max(s,ans(j));

    }

    cout<<s;

}

// Faster C++ solution for the same problem (measured speedup: 3.945766384187158x):
#include<cstdio>

#include<cstring>

#include<iostream>

#include<algorithm>

#include<queue>

using namespace std;

const int maxn=100000+10;

struct node

{

	int to,next,w;

}edge[maxn];

int k=1,head[maxn],ind[maxn],n,m,dp[maxn];

void add(int u,int v,int w)

{

	edge[++k].to=v;edge[k].next=head[u];head[u]=k;edge[k].w=w;

}

void Topsort()

{

	queue<int>q;

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

		if(!ind[i])

			q.push(i);

	while(!q.empty())

	{

		int x=q.front();q.pop();

		for(int i=head[x];i;i=edge[i].next)

		{

			dp[edge[i].to]=max(dp[edge[i].to],dp[x]+edge[i].w);

			ind[edge[i].to]--;

			if(!ind[edge[i].to])

				q.push(edge[i].to);

		}

	}

}

int  main()

{

	cin>>n>>m;

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

	{

		int u,v;

		cin>>u>>v;

		add(u,v,1);

		ind[v]++;

	}

	Topsort();

	int ans=0;

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

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

	cout<<ans<<endl;

	return 0;

}