stablegradients/pie-gem5-bysrc huggingface dataset:
// Original C++ solution (slower):
#include<bits/stdc++.h>

using namespace std;

 

#define             ll  long long

#define            ull  unsigned long long

#define            P_B  push_back

#define            M_P  make_pair

#define         DBG(x)  printf("%s %d\n", #x, x)

#define       DBGLL(x)  printf("%s %lld\n", #x, x)

#define         SCI(x)  scanf("%d",&x)

#define         SCD(x)  scanf("%lf",&x)

#define         SCS(x)  scanf("%s",x)

#define         CLR(x)  memset(x, 0, sizeof(x))

#define        CLRN(x)  memset(x, -1, sizeof(x))

#define        SCLL(x)  scanf("%lld", &x)

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

#define  FORR(i, m, n)  for(int i = m; i < n; i++)

#define     SCI2(m, n)  scanf("%d%d", &m, &n)

#define  SCI3(m, n, o)  scanf("%d%d%d",&m, &n, &o)

#define     SCD2(m, n)  scanf("%lf%lf",&m,&n)

#define  SCD3(m, n, o)  scanf("%lf%lf%lf",&m,&n,&o)

#define    SCLL2(m, n)  scanf("%lld%lld", &m, &n)

#define SCLL3(m, n, o)  scanf("%lld%lld%lld",&m, &n, &o)

#define             vi  vector<int>

#define            vii  vector<pair<int, int> >

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

#define            Mod  1000000007

#define            INF  1000000000

 



int n, m;

queue<int> st;

vi node[100001];

vector<bool> selected(100001, false);

vector<bool> visited(100001, false);

int maxxes[100001];



void topsort(int v)

{

	if(selected[v]) return;

	selected[v] = true;

	for(auto it : node[v]){

		if(!selected[it]){

			topsort(it);

		}

	}

	st.push(v);

}



int notdfs(int v, int cnt)

{

	// cnt++;

	visited[v] = true;

	int mx =  -1;

	// DBG(mx);

	// DBG(v);

	for(auto it : node[v]){

		// if(!visited[it]){

			mx = max(mx, maxxes[it]);

			// DBG(mx);

			// DBG(it);

		// }

	}

	maxxes[v] = mx + 1;

	return mx + 1;

}



int main()

{

	SCI2(n, m);

	FORR(i, 1, m + 1){

		int p, q;

		SCI2(p, q);

		node[p].P_B(q);

	}

	FORR(i, 1, n + 1)topsort(i);

	int max_ = 0;

	FORR(i, 1, n + 1){

		int x = st.front();

		// DBG(x);

		st.pop();

		if(!visited[x]){

			max_ = max(max_, notdfs(x, -1));

		}

	}

	// FORR(i, 1, n + 1) printf("%d ", maxxes[i]);

	// cout << endl;

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

}

// Optimized solution to the same problem (faster):
#include <queue>

#include <iostream>

using namespace std;

const int MAXN=1e5+7;

struct EDGE {int n,next;} edge[MAXN];

int n,m,cnt,ans;

int in[MAXN],dis[MAXN],head[MAXN];

queue <int> q;

void Add(int x,int y)

{

	edge[++cnt].n=y,edge[cnt].next=head[x],head[x]=cnt;

}

void Topo()

{

	while(!q.empty())

	{

		int x=q.front();

		q.pop();

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

		{

			in[edge[i].n]--;

			dis[edge[i].n]=dis[x]+1;

			ans=max(ans,dis[edge[i].n]);

			if(!in[edge[i].n]) q.push(edge[i].n);

		}

	}

}

int main()

{

	cin>>n>>m;

	for(int x,y,i=1;i<=m;i++) cin>>x>>y,Add(x,y),in[y]++;

	for(int i=1;i<=n;i++) if(!in[i]) q.push(i);

	Topo();

	cout<<ans<<endl;

	return 0;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include<bits/stdc++.h>

using namespace std;

const int maxn = 1e5 + 5;

vector<int>G[maxn];

queue<int> q;

int in[maxn];

int n,m;

int ans = 0;

int dp[maxn];

void topu(){

	while(!q.empty()) q.pop();

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

		if(in[i] == 0) q.push(i);

		//if(in[i] == 0) printf("%d\n",i);

	}

	while(!q.empty()){

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

		int len = G[hh].size();

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

			int tmp = G[hh][i];

			//printf("%d\n",tmp);

			in[tmp]--;

			dp[tmp] = max(dp[tmp],dp[hh] + 1);

			if(in[tmp] == 0) q.push(tmp);

		}

		//ans++;

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

	}

	return ;

}

int main(){

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

	int x,y;

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

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

		G[x].push_back(y);

		in[y]++;

	}

	topu();

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

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

	cout << ans << endl;

	return 0;

}

// Optimized solution to the same problem (faster):
#include <queue>

#include <iostream>

using namespace std;

const int MAXN=1e5+7;

struct EDGE {int n,next;} edge[MAXN];

int n,m,cnt,ans;

int in[MAXN],dis[MAXN],head[MAXN];

queue <int> q;

void Add(int x,int y)

{

	edge[++cnt].n=y,edge[cnt].next=head[x],head[x]=cnt;

}

void Topo()

{

	while(!q.empty())

	{

		int x=q.front();

		q.pop();

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

		{

			in[edge[i].n]--;

			dis[edge[i].n]=dis[x]+1;

			ans=max(ans,dis[edge[i].n]);

			if(!in[edge[i].n]) q.push(edge[i].n);

		}

	}

}

int main()

{

	cin>>n>>m;

	for(int x,y,i=1;i<=m;i++) cin>>x>>y,Add(x,y),in[y]++;

	for(int i=1;i<=n;i++) if(!in[i]) q.push(i);

	Topo();

	cout<<ans<<endl;

	return 0;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include<bits/stdc++.h>

using namespace std;



int n, m;

vector<int>ady[100001];

vector<int>topoSort;

vector<int>who[100001];

bool visitado[100001];

int memo[100001];



void dfs(int nodo){

    visitado[nodo] = true;

    for(int i : ady[nodo])

        if (!visitado[i])

            dfs(i);

    topoSort.push_back(nodo);

}



void topological_sort(){

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

        if(!visitado[i])

            dfs(i);

}



int dp(int nodo){

    if(who[nodo].size() == 0)//es nodo raiz

        return  1;

    if(memo[nodo])

        return memo[nodo];

    int Max = 0;

    for(auto i : who[nodo])

        memo[nodo] = max(memo[nodo], dp(i) + 1);

    return memo[nodo];

}



int maxPath(){

    topological_sort();

    //hacemos orden topologico

    // for(int i = 0; i < n; i++)

    //     cout<<topoSort[i]<<" ";

    // cout<<endl;

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

    //     cout<<i<<": ";

    //     for(auto j : who[i])

    //         cout<<j<<" ";

    //     cout<<endl;

    // }

    // cout<<endl;

    // exit(0);

    int Max = -1;

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

        Max = max(Max, dp(topoSort[i]));

    return Max;

}



int main(){



    cin.tie(0);

    ios_base::sync_with_stdio(0);



    cin>>n>>m;



    while(m--){

        int a, b;

        cin>>a>>b;

        ady[a].push_back(b);

        who[b].push_back(a);

    }

    cout<<maxPath() - 1;

}

// Optimized solution to the same problem (faster):
#include <queue>

#include <iostream>

using namespace std;

const int MAXN=1e5+7;

struct EDGE {int n,next;} edge[MAXN];

int n,m,cnt,ans;

int in[MAXN],dis[MAXN],head[MAXN];

queue <int> q;

void Add(int x,int y)

{

	edge[++cnt].n=y,edge[cnt].next=head[x],head[x]=cnt;

}

void Topo()

{

	while(!q.empty())

	{

		int x=q.front();

		q.pop();

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

		{

			in[edge[i].n]--;

			dis[edge[i].n]=dis[x]+1;

			ans=max(ans,dis[edge[i].n]);

			if(!in[edge[i].n]) q.push(edge[i].n);

		}

	}

}

int main()

{

	cin>>n>>m;

	for(int x,y,i=1;i<=m;i++) cin>>x>>y,Add(x,y),in[y]++;

	for(int i=1;i<=n;i++) if(!in[i]) q.push(i);

	Topo();

	cout<<ans<<endl;

	return 0;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <bits/stdc++.h>

using namespace std;

#define ll long long

#define ull unsigned long long

#define PII pair<int,int>

#define PSI pair<string,int>

#define PIII pair< int, pair<int,int> >

const int MaxN = 1e5+5;

vector<int> g[MaxN];

int dp[MaxN];

int N;



int dfs(int node){



    auto &ret = dp[node];

    if(ret!=-1) return ret;

    ret = 0;

    for(auto i: g[node])

        ret = max( ret, dfs(i)+1 );

    return ret;

}



void read(){



    int i,edge;

    memset(dp,-1,sizeof dp);

    cin>>N>>edge;

    for(i=0; i<edge; i++){

        int u,v;

        cin>>u>>v;

        g[u].push_back(v);

    }

}



void solve(){



    read();

    int res = 0;

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

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

    }



    cout<< res << "\n";

}



int main(){



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

    ios_base::sync_with_stdio(false);

    cin.tie(nullptr);

    solve();

    return 0;

}


// Optimized solution to the same problem (faster):
#include <queue>

#include <iostream>

using namespace std;

const int MAXN=1e5+7;

struct EDGE {int n,next;} edge[MAXN];

int n,m,cnt,ans;

int in[MAXN],dis[MAXN],head[MAXN];

queue <int> q;

void Add(int x,int y)

{

	edge[++cnt].n=y,edge[cnt].next=head[x],head[x]=cnt;

}

void Topo()

{

	while(!q.empty())

	{

		int x=q.front();

		q.pop();

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

		{

			in[edge[i].n]--;

			dis[edge[i].n]=dis[x]+1;

			ans=max(ans,dis[edge[i].n]);

			if(!in[edge[i].n]) q.push(edge[i].n);

		}

	}

}

int main()

{

	cin>>n>>m;

	for(int x,y,i=1;i<=m;i++) cin>>x>>y,Add(x,y),in[y]++;

	for(int i=1;i<=n;i++) if(!in[i]) q.push(i);

	Topo();

	cout<<ans<<endl;

	return 0;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <bits/stdc++.h>

 

using namespace std;

 

typedef long long ll;

typedef vector<ll> vi;

typedef long double td;

typedef vector<td> vd;

typedef pair<ll,ll> ii;

typedef vector<ii> vii; typedef vector<bool> vb;

#define FIN ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)

#define forr(i, a, b) for(ll i = ll(a); i < (ll)(b); i++)

#define forn(i, n) forr(i, 0, n)

#define pb push_back

#define mp make_pair

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

#define DBG(x) cerr << #x << " = " << (x) << endl

#define show(v,n) cerr << #v << " = "; forn(i,n) cerr << v[i] << " "; cerr << endl;

#define esta(x,c) ((c).find(x) != (c).end())

#define RAYA cerr << "===============================" << endl

int MAXN = 500005;



vector <int> v[100005];

vector <int> dp(100005,0);

vector <bool> visto(100005,false);



void DFS(int n)

{

	visto[n]=true;

	for(auto u : v[n])

	{

		if(!visto[u]) DFS(u);

		dp[n]=max(dp[n],dp[u]+1);

	}

}

 

int main()

{ 	

	FIN;

	#ifdef input

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

	#endif



	int n, m;

	cin >> n >> m;

	forn(i,m)

	{

		int x, y;

		cin >> x >> y;

		v[x].pb(y);

	}

	forn(i,n+1)

	{

		if(visto[i]==false) DFS(i);

	}

	int ans = 0;

	forn(i,n+1) ans = max(ans,dp[i]);

	cout << ans << endl;

    return 0;

}

// Optimized solution to the same problem (faster):
#include <queue>

#include <iostream>

using namespace std;

const int MAXN=1e5+7;

struct EDGE {int n,next;} edge[MAXN];

int n,m,cnt,ans;

int in[MAXN],dis[MAXN],head[MAXN];

queue <int> q;

void Add(int x,int y)

{

	edge[++cnt].n=y,edge[cnt].next=head[x],head[x]=cnt;

}

void Topo()

{

	while(!q.empty())

	{

		int x=q.front();

		q.pop();

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

		{

			in[edge[i].n]--;

			dis[edge[i].n]=dis[x]+1;

			ans=max(ans,dis[edge[i].n]);

			if(!in[edge[i].n]) q.push(edge[i].n);

		}

	}

}

int main()

{

	cin>>n>>m;

	for(int x,y,i=1;i<=m;i++) cin>>x>>y,Add(x,y),in[y]++;

	for(int i=1;i<=n;i++) if(!in[i]) q.push(i);

	Topo();

	cout<<ans<<endl;

	return 0;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <bits/stdc++.h>

#define endl '\n'

using namespace std;



const int MXN = 1e5 + 5;

int n, m;

int dp[MXN];

vector<int> g[MXN];



int dfs(int u) {

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

    int ans = 0;

    for(auto & v: g[u]) {

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

    }

    return dp[u] = ans;

}



int main() {

    ios_base::sync_with_stdio(false); cin.tie(NULL);

    cin >> n >> m;

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

        int u, v; cin >> u >> v;

        u--, v--;

        g[u].emplace_back(v);

    }

    memset(dp, -1, sizeof dp);

    int ans = 0;

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

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

    }

    cout << ans << endl;

    return 0;

}

// Optimized solution to the same problem (faster):
#include <queue>

#include <iostream>

using namespace std;

const int MAXN=1e5+7;

struct EDGE {int n,next;} edge[MAXN];

int n,m,cnt,ans;

int in[MAXN],dis[MAXN],head[MAXN];

queue <int> q;

void Add(int x,int y)

{

	edge[++cnt].n=y,edge[cnt].next=head[x],head[x]=cnt;

}

void Topo()

{

	while(!q.empty())

	{

		int x=q.front();

		q.pop();

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

		{

			in[edge[i].n]--;

			dis[edge[i].n]=dis[x]+1;

			ans=max(ans,dis[edge[i].n]);

			if(!in[edge[i].n]) q.push(edge[i].n);

		}

	}

}

int main()

{

	cin>>n>>m;

	for(int x,y,i=1;i<=m;i++) cin>>x>>y,Add(x,y),in[y]++;

	for(int i=1;i<=n;i++) if(!in[i]) q.push(i);

	Topo();

	cout<<ans<<endl;

	return 0;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include<iostream>

#include<algorithm>

#include<queue>

#include<cstring>

#include<cstdio>

#include<cmath>

#include<set>

#include<map>

#include<vector>

#include<cmath>

#include<ctime>



using namespace std;

const int maxn = 1e5 + 7;

const int inf = 0x3f3f3f3f;

const int mod = 1e9 + 7;

const double pi = acos(-1.0);

typedef long long ll;

#define pb push_back



int n, m;

int dp[maxn];

int in[maxn];



int main(){

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

	queue<int>q;

	vector<int> vt[maxn];

	memset(dp, 0, sizeof dp);

	int u, v;

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

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

		vt[u].pb(v);

		in[v]++;

	}

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

		if(in[i] == 0) q.push(i);



	int now;

	int ans = 0;

	while(!q.empty()){

		now = q.front();

		q.pop();

		int len = vt[now].size();

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

			int t = vt[now][i];

			dp[t] = max(dp[t], dp[now] + 1);

			in[t]--;

			if(in[t] == 0) q.push(t);

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

		}

	}

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

}

// Optimized solution to the same problem (faster):
#include <queue>

#include <iostream>

using namespace std;

const int MAXN=1e5+7;

struct EDGE {int n,next;} edge[MAXN];

int n,m,cnt,ans;

int in[MAXN],dis[MAXN],head[MAXN];

queue <int> q;

void Add(int x,int y)

{

	edge[++cnt].n=y,edge[cnt].next=head[x],head[x]=cnt;

}

void Topo()

{

	while(!q.empty())

	{

		int x=q.front();

		q.pop();

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

		{

			in[edge[i].n]--;

			dis[edge[i].n]=dis[x]+1;

			ans=max(ans,dis[edge[i].n]);

			if(!in[edge[i].n]) q.push(edge[i].n);

		}

	}

}

int main()

{

	cin>>n>>m;

	for(int x,y,i=1;i<=m;i++) cin>>x>>y,Add(x,y),in[y]++;

	for(int i=1;i<=n;i++) if(!in[i]) q.push(i);

	Topo();

	cout<<ans<<endl;

	return 0;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include<cstdio>

#include<math.h>

#include<cstring>

#include<algorithm>

#include<iostream>

#include<set>

#include<map>

#include<queue>

using namespace std;

#define Case int t;scanf("%d", &t);while(t--)

typedef long long ll;

const int Max = 1e5 + 5;

const int INF = 0x3f3f3f3f;

const double PI = acos(-1.0);

int n, m;

int dp[Max];

int in[Max];

vector<int> G[Max];

queue<int> que;

int main(){

	cin >> n >> m;

	int u, v;

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

		cin >> u >> v;

		G[u].push_back(v);

		in[v]++;

	}



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

		if(!in[i]) que.push(i);

	}



	int ans = 0;

	while(!que.empty()){

		int now = que.front();

		que.pop();

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

			dp[G[now][i]] = max(dp[G[now][i]], dp[now]+1);

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

			in[G[now][i]]--;

			if(!in[G[now][i]]) que.push(G[now][i]);

		}

	}



	cout << ans << endl;

}


// Optimized solution to the same problem (faster):
#include <queue>

#include <iostream>

using namespace std;

const int MAXN=1e5+7;

struct EDGE {int n,next;} edge[MAXN];

int n,m,cnt,ans;

int in[MAXN],dis[MAXN],head[MAXN];

queue <int> q;

void Add(int x,int y)

{

	edge[++cnt].n=y,edge[cnt].next=head[x],head[x]=cnt;

}

void Topo()

{

	while(!q.empty())

	{

		int x=q.front();

		q.pop();

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

		{

			in[edge[i].n]--;

			dis[edge[i].n]=dis[x]+1;

			ans=max(ans,dis[edge[i].n]);

			if(!in[edge[i].n]) q.push(edge[i].n);

		}

	}

}

int main()

{

	cin>>n>>m;

	for(int x,y,i=1;i<=m;i++) cin>>x>>y,Add(x,y),in[y]++;

	for(int i=1;i<=n;i++) if(!in[i]) q.push(i);

	Topo();

	cout<<ans<<endl;

	return 0;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
//G

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int maxn = 1e5+10;

vector<int>G[maxn];

ll f[maxn];

ll dfs(int u){

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

	f[u] = 1;

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

	return f[u];

}

int main(){

	int n,m;

	cin >> n >> m;

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

		int f,t;

		cin >> f >> t;

		G[f].push_back(t);

	}

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

	ll ans = -1;

	for(int i = 1;i <= n;i++)ans = max(ans,f[i]);

	cout << ans-1;

	return 0;

}


// Optimized solution to the same problem (faster):
#include <queue>

#include <iostream>

using namespace std;

const int MAXN=1e5+7;

struct EDGE {int n,next;} edge[MAXN];

int n,m,cnt,ans;

int in[MAXN],dis[MAXN],head[MAXN];

queue <int> q;

void Add(int x,int y)

{

	edge[++cnt].n=y,edge[cnt].next=head[x],head[x]=cnt;

}

void Topo()

{

	while(!q.empty())

	{

		int x=q.front();

		q.pop();

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

		{

			in[edge[i].n]--;

			dis[edge[i].n]=dis[x]+1;

			ans=max(ans,dis[edge[i].n]);

			if(!in[edge[i].n]) q.push(edge[i].n);

		}

	}

}

int main()

{

	cin>>n>>m;

	for(int x,y,i=1;i<=m;i++) cin>>x>>y,Add(x,y),in[y]++;

	for(int i=1;i<=n;i++) if(!in[i]) q.push(i);

	Topo();

	cout<<ans<<endl;

	return 0;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <bits/stdc++.h> //G - Longest Path

#define f first

#define s second

#define pb push_back

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

using namespace std;

const int maxn = 100100;





typedef long long int ll;

typedef pair<int,int> ii;



int dp[maxn]; //dp[i] = maior caminho começando de i

int n,m,ans;

vector<int> filho[maxn];



void dfs(int x)

{

	int best = 0;



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

	{

		int y = filho[x][i];

		if(dp[y] == 0)

			dfs(y);		

		best = max(best,dp[y]);

	}



	dp[x] = best + 1;

}



int main()

{

	ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);

	

	cin>>n>>m;



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



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

	{

		int a,b;

		cin>>a>>b;

		filho[a].pb(b);

	}

	

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

		if(dp[i] == 0) dfs(i);



	int best = 0;

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

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

	cout<<best-1<<"\n";



}

// Optimized solution to the same problem (faster):
#include <queue>

#include <iostream>

using namespace std;

const int MAXN=1e5+7;

struct EDGE {int n,next;} edge[MAXN];

int n,m,cnt,ans;

int in[MAXN],dis[MAXN],head[MAXN];

queue <int> q;

void Add(int x,int y)

{

	edge[++cnt].n=y,edge[cnt].next=head[x],head[x]=cnt;

}

void Topo()

{

	while(!q.empty())

	{

		int x=q.front();

		q.pop();

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

		{

			in[edge[i].n]--;

			dis[edge[i].n]=dis[x]+1;

			ans=max(ans,dis[edge[i].n]);

			if(!in[edge[i].n]) q.push(edge[i].n);

		}

	}

}

int main()

{

	cin>>n>>m;

	for(int x,y,i=1;i<=m;i++) cin>>x>>y,Add(x,y),in[y]++;

	for(int i=1;i<=n;i++) if(!in[i]) q.push(i);

	Topo();

	cout<<ans<<endl;

	return 0;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include<bits/stdc++.h>

#define ll long long

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

using namespace std;

double PI=acos(-1);

vector<int> adj[100005];

int dp[100005];

bool vis[100005];

int solve(int node){

    if(vis[node])

        return dp[node];

    vis[node]=1;

    int ret=1;

    for(auto v:adj[node])

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

    return dp[node]=ret;

}



int main(){

    int n,m,ans=0;cin>>n>>m;

    for(int i=0;i<100005;i++) dp[i]=1;

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

        int x,y;cin>>x>>y;

        adj[x].push_back(y);

    }

    for(int i=1;i<=n;i++) ans=max(ans,solve(i));

    cout<<ans-1<<'\n';















    return 0;

}


// Optimized solution to the same problem (faster):
#include <queue>

#include <iostream>

using namespace std;

const int MAXN=1e5+7;

struct EDGE {int n,next;} edge[MAXN];

int n,m,cnt,ans;

int in[MAXN],dis[MAXN],head[MAXN];

queue <int> q;

void Add(int x,int y)

{

	edge[++cnt].n=y,edge[cnt].next=head[x],head[x]=cnt;

}

void Topo()

{

	while(!q.empty())

	{

		int x=q.front();

		q.pop();

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

		{

			in[edge[i].n]--;

			dis[edge[i].n]=dis[x]+1;

			ans=max(ans,dis[edge[i].n]);

			if(!in[edge[i].n]) q.push(edge[i].n);

		}

	}

}

int main()

{

	cin>>n>>m;

	for(int x,y,i=1;i<=m;i++) cin>>x>>y,Add(x,y),in[y]++;

	for(int i=1;i<=n;i++) if(!in[i]) q.push(i);

	Topo();

	cout<<ans<<endl;

	return 0;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <cstdio>

#include <cstring>

#include <iostream>

#include <queue>

#include <cmath>

#include <map>

#include <stack>

#include <set>

#include <sstream>

#include <vector>

#include <stdlib.h>

#include <algorithm>

using namespace std;





typedef long long ll;

const int MAX_N = 100025;

int dp[MAX_N],in[MAX_N];

vector<int > G[MAX_N];

int main()

{

   

    queue<int > q;

    int n,m,a,b,ans = 0;scanf("%d%d",&n,&m);

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

	scanf("%d%d",&a,&b),in[b]++,G[a].push_back(b);

    for(int i = 1;i<=n;++i) if(!in[i]) q.push(i);

    while(!q.empty())

    {

        int now = q.front();

        q.pop();

        int sz = G[now].size();

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

        {

            dp[G[now][i]] = max(dp[G[now][i]],dp[now]+1);

            in[G[now][i]]--;

            if(in[G[now][i]]==0) q.push(G[now][i]);

        }

    }

    for(int i = 1;i<=n;++i) ans = max(ans,dp[i]);

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

    return 0;

}


// Optimized solution to the same problem (faster):
#include <bits/stdc++.h>

#define f first

#define s second

#define pb push_back

#define ENDL '\n'

#define all(a) begin(a), end(a)

#define sz(a) (int)(a.size())

#define deb(a) cout << #a << ": " << a << ENDL

#define fore(i, a, b) for(int i(a), ThkMk(b); i < ThkMk; ++i)

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



using namespace std;



typedef long long lli;

typedef long double ld;

typedef pair<lli, lli> ii;

typedef vector<lli> vi;



vector<vector<lli>> graph;

vector<lli> dp;



int dfs(int u) {

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

    int ret = 0;

    for(auto it : graph[u]) {

        ret = max(ret, dfs(it) + 1);

    }

    dp[u] = ret;

    return ret;

}



int main()

{   _

    lli n, m, u, v; cin >> n >> m;

    graph.resize(n + 1);

    dp.resize(n + 1);

    fill(all(dp), -1);

    fore(i, 0, m) {

        cin >> u >> v;

        graph[u].pb(v);

    }

    int mx = 0;

    fore(i, 1, n + 1) mx = max(mx, dfs(i));

    cout << mx << ENDL;

    return 0;

}


// Fastest known solution for this problem: