stablegradients/pie-gem5-pairs huggingface dataset:
// Slower C++ solution:
#include<cstdio>

#include<algorithm>

#include<vector>

using namespace std;



typedef long long ll;

const int MAXN=1e5+5;



int n,m,flag;

int cnt[3],ncnt,ecnt,c[MAXN];

bool vis[MAXN],evis[MAXN];

struct node{

    int v,w,id;

    node(int _v,int _w,int _id):v(_v),w(_w),id(_id){}

};

vector<node> E[MAXN];



void dfs(int u){

    vis[u]=1;

    ncnt++;

    cnt[c[u]]++;

    for(int i=0;i<(int)E[u].size();i++){

        int v=E[u][i].v,w=E[u][i].w,id=E[u][i].id;

        if(evis[id]) continue; evis[id]=1; ecnt++;

        if(!vis[v]){

            c[v]=(c[u]+w+3)%3;

            dfs(v);

        }

        else if(c[v]!=(c[u]+w+3)%3) flag=1;

    }

}



int main(){



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

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

	    int u,v;

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

        E[u].push_back(node(v,1,i));

        E[v].push_back(node(u,-1,i));

	}

	ll ans=0;

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

        if(vis[i]) continue;

        flag=ncnt=ecnt=cnt[0]=cnt[1]=cnt[2]=0;

        dfs(i);

        if(flag) ans+=1ll*ncnt*ncnt;

        else if(!cnt[0]||!cnt[1]||!cnt[2]) ans+=ecnt;

        else ans+=1ll*cnt[0]*cnt[1]+1ll*cnt[1]*cnt[2]+1ll*cnt[2]*cnt[0];

    }

    printf("%lld",ans);



	fclose(stdin);

	fclose(stdout);

}


// Faster C++ solution for the same problem (measured speedup: 3.499743999711848x):
#include<bits/stdc++.h>

using namespace std;

#define ll long long

#define REP(i,a,b) for(int i=(a),_end_=(b);i<=_end_;i++)

#define DREP(i,a,b) for(int i=(a),_end_=(b);i>=_end_;i--)

#define EREP(i,u) for(int i=start[u];i;i=e[i].next)

#define fi first

#define se second

#define mkr(a,b) make_pair(a,b)

#define SZ(A) ((int)A.size())

template<class T>inline void chkmin(T &a,T b){ if(a>b)a=b;}

template<class T>inline void chkmax(T &a,T b){ if(a<b)a=b;}

inline int read()

{

	int s=0,f=1;char ch=getchar();

	while(!isdigit(ch) && ch!='-')ch=getchar();

	if(ch=='-')ch=getchar(),f=-1;

	while(isdigit(ch))s=s*10+ch-'0',ch=getchar();

	return ~f?s:-s;

}



const int maxn=1e5+20;



struct node {

	int v,next,w;

};

node e[maxn<<1];

int cnt,start[maxn];

inline void addedge(int u,int v,int w){ e[++cnt]=(node){v,start[u],w};start[u]=cnt;}



int n,m;



int vis[maxn],dis[maxn];



inline void init()

{

	n=read();m=read();

	REP(i,1,m)

	{

		int u=read(),v=read();

		addedge(u,v,1);

		addedge(v,u,2);

	}

}



int num[3],EDGE;

int flg;



void dfs(int u)

{

	++num[dis[u]]; vis[u]=1;

	EREP(i,u)

	{

		EDGE++;

		int v=e[i].v;

		if(vis[v])

		{

			if(dis[v]==(dis[u]+e[i].w)%3)continue;

			else flg=1;

		}else dis[v]=(dis[u]+e[i].w)%3,dfs(v);

	}

}



ll ans;



inline void doing()

{

	REP(i,1,n)if(!vis[i])

	{

		memset(num,0,sizeof(num));EDGE=0;

		flg=0;

		dfs(i);

		int all=num[0]+num[1]+num[2];

		if(flg)ans+=(ll)all*all;

		else {

			if(num[0] && num[1] && num[2])REP(op,0,2)ans+=(ll)num[op]*num[(op+1)%3];

			else ans+=EDGE>>1;

		}

	}

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

}



int main()

{

	init();

	doing();

	return 0;

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

#include <cstring>

#include <vector>

using namespace std;

typedef long long i64;

const int MAXN = 1e5 + 10;



i64 answer;

i64 totCnt;

i64 N, M;

i64 check[MAXN];

i64 cnt[3];



bool flag;



vector<pair<i64, i64> > Adj[MAXN];



inline void addEdge(i64 u, i64 v, i64 w)

{

	Adj[u].emplace_back(v, w);

}



void DFS(int cur)

{

	cnt[check[cur]] ++;



	for(auto x : Adj[cur])

	{

		totCnt += (x.second == 1);



		if(check[x.first] != -1)

		{

			if((check[cur] + x.second) % 3 != check[x.first])

				flag = true;

		}

		else

		{

			check[x.first] = (check[cur] + x.second) % 3;

			DFS(x.first);

		}

	}

}



int main()

{

	ios::sync_with_stdio(false), cin.tie(nullptr);



	cin >> N >> M;

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

	{

		i64 u, v;

		cin >> u >> v;

		addEdge(u, v, 1);

		addEdge(v, u, 2);

	}



	memset(check, -1, sizeof check);



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

	{

		if(check[i] != -1)

			continue;



		check[i] = 0, totCnt = 0;

		cnt[0] = cnt[1] = cnt[2] = 0;

		flag = false;



		DFS(i);

		if(flag)

			answer += (cnt[0] + cnt[1] + cnt[2]) * (cnt[0] + cnt[1] + cnt[2]);

		else if(!cnt[0] || !cnt[1] || !cnt[2])

			answer += totCnt;

		else

			answer += cnt[0] * cnt[1] + cnt[1] * cnt[2] + cnt[2] * cnt[0];



	}



	cout << answer << endl ;



	return 0;

}

// Faster C++ solution for the same problem (measured speedup: 4.469082915627463x):
#include<bits/stdc++.h>

using namespace std;

#define ll long long

#define REP(i,a,b) for(int i=(a),_end_=(b);i<=_end_;i++)

#define DREP(i,a,b) for(int i=(a),_end_=(b);i>=_end_;i--)

#define EREP(i,u) for(int i=start[u];i;i=e[i].next)

#define fi first

#define se second

#define mkr(a,b) make_pair(a,b)

#define SZ(A) ((int)A.size())

template<class T>inline void chkmin(T &a,T b){ if(a>b)a=b;}

template<class T>inline void chkmax(T &a,T b){ if(a<b)a=b;}

inline int read()

{

	int s=0,f=1;char ch=getchar();

	while(!isdigit(ch) && ch!='-')ch=getchar();

	if(ch=='-')ch=getchar(),f=-1;

	while(isdigit(ch))s=s*10+ch-'0',ch=getchar();

	return ~f?s:-s;

}



const int maxn=1e5+20;



struct node {

	int v,next,w;

};

node e[maxn<<1];

int cnt,start[maxn];

inline void addedge(int u,int v,int w){ e[++cnt]=(node){v,start[u],w};start[u]=cnt;}



int n,m;



int vis[maxn],dis[maxn];



inline void init()

{

	n=read();m=read();

	REP(i,1,m)

	{

		int u=read(),v=read();

		addedge(u,v,1);

		addedge(v,u,2);

	}

}



int num[3],EDGE;

int flg;



void dfs(int u)

{

	++num[dis[u]]; vis[u]=1;

	EREP(i,u)

	{

		EDGE++;

		int v=e[i].v;

		if(vis[v])

		{

			if(dis[v]==(dis[u]+e[i].w)%3)continue;

			else flg=1;

		}else dis[v]=(dis[u]+e[i].w)%3,dfs(v);

	}

}



ll ans;



inline void doing()

{

	REP(i,1,n)if(!vis[i])

	{

		memset(num,0,sizeof(num));EDGE=0;

		flg=0;

		dfs(i);

		int all=num[0]+num[1]+num[2];

		if(flg)ans+=(ll)all*all;

		else {

			if(num[0] && num[1] && num[2])REP(op,0,2)ans+=(ll)num[op]*num[(op+1)%3];

			else ans+=EDGE>>1;

		}

	}

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

}



int main()

{

	init();

	doing();

	return 0;

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

#include<cstdio>

#include<cstdlib>

#include<cstring>

#include<algorithm>

using namespace std;



#define ll long long

#define mem(Arr,x) memset(Arr,x,sizeof(Arr))



const int maxN=100010;

const int maxM=maxN*2;

const int inf=2147483647;



int n,m;

int edgecnt=-1,Head[maxN],Next[maxM],V[maxM],W[maxM];

int Col[maxN];

bool getring;

ll edge,node;

bool vis[maxN];

ll Aper[3];



void Add_Edge(int u,int v,int w);

void dfs(int u,int col);



int main()

{

	ios::sync_with_stdio(false);mem(Head,-1);

	cin>>n>>m;

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

		int u,v;cin>>u>>v;Add_Edge(u,v,1);Add_Edge(v,u,2);

	}

	mem(Col,-1);

	ll Ans=0;

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

		if (Col[i]==-1)

		{

			getring=0;edge=0;node=0;Aper[0]=Aper[1]=Aper[2]=0;

			dfs(i,0);

			//cout<<getring<<" "<<edge<<" "<<node<<" "<<Aper[0]<<" "<<Aper[1]<<" "<<Aper[2]<<endl;

			if (getring) Ans+=(ll)node*node;

			else if ((Aper[0]==0)||(Aper[1]==0)||(Aper[2]==0)) Ans+=edge;

			else Ans+=(ll)Aper[0]*Aper[1]+(ll)Aper[1]*Aper[2]+(ll)Aper[2]*Aper[0];

		}

	cout<<Ans<<endl;

	return 0;

}



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

{

	edgecnt++;Next[edgecnt]=Head[u];Head[u]=edgecnt;V[edgecnt]=v;W[edgecnt]=w;

	return;

}



void dfs(int u,int col)

{

	if (Col[u]!=-1)

	{

		if (Col[u]!=col) getring=1;

		return;

	}

	

	Col[u]=col;Aper[col]++;node++;

	for (int i=Head[u];i!=-1;i=Next[i])

	{

		if (vis[i>>1]==0) vis[i>>1]=1,edge++;

		dfs(V[i],(col+W[i])%3);

	}

	return;

}


// Faster C++ solution for the same problem (measured speedup: 1.8261534985857617x):
#include<bits/stdc++.h>

using namespace std;

const int N=2e5+10;

typedef long long ll;

int gi() {

    int x=0,o=1;char ch=getchar();

    while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();

    if(ch=='-') o=-1,ch=getchar();

    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();

    return x*o;

}

struct edge { int to,w,nxt; } e[N<<1];

int tot=1,h[N];

void adde(int u,int v) {

    e[++tot]=(edge){v,1,h[u]};h[u]=tot;

    e[++tot]=(edge){u,-1,h[v]};h[v]=tot;

}

int n,m,V,E,col[N],cnt[3];

bool vis[N],vise[N];

ll ans=0;

bool flag=0;

void dfs(int u) {

    V++;vis[u]=1;

    cnt[col[u]]++;

    for(int i=h[u];i;i=e[i].nxt) {

        if(vise[i>>1]) continue; vise[i>>1]=1,E++;

        int v=e[i].to;

        if(!vis[v]) col[v]=(col[u]+e[i].w+3)%3,dfs(v);

        else if(col[v]!=(col[u]+e[i].w+3)%3) flag=1;

    }

}

int main() {

    cin>>n>>m;

    for(int i=1,u,v;i<=m;i++) u=gi(),v=gi(),adde(u,v);

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

        if(!vis[i]) {

            V=E=cnt[0]=cnt[1]=cnt[2]=0;flag=0;dfs(i);

            if(flag) ans+=1ll*V*V;

            else if(!cnt[0]||!cnt[1]||!cnt[2]) ans+=E;

            else ans+=1ll*cnt[0]*cnt[1]+1ll*cnt[1]*cnt[2]+1ll*cnt[2]*cnt[0];

        }

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

    return 0;

}

//orzgzy

//鸡贼明年进队超稳
// Slower C++ solution:
#include<bits/stdc++.h>

using namespace std;

const int N=2e5+10;

typedef long long ll;

int gi() {

    int x=0,o=1;char ch=getchar();

    while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();

    if(ch=='-') o=-1,ch=getchar();

    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();

    return x*o;

}

struct edge { int to,w,nxt; } e[N<<1];

int tot=1,h[N];

void adde(int u,int v) {

    e[++tot]=(edge){v,1,h[u]};h[u]=tot;

    e[++tot]=(edge){u,-1,h[v]};h[v]=tot;

}

int n,m,V,E,col[N],cnt[3];

bool vis[N],vise[N];

ll ans=0;

bool flag=0;

void dfs(int u) {

    V++;vis[u]=1;

    cnt[col[u]]++;

    for(int i=h[u];i;i=e[i].nxt) {

        if(vise[i>>1]) continue; vise[i>>1]=1,E++;

        int v=e[i].to;

        if(!vis[v]) col[v]=(col[u]+e[i].w+3)%3,dfs(v);

        else if(col[v]!=(col[u]+e[i].w+3)%3) flag=1;

    }

}

int main() {

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

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

    cin>>n>>m;

    for(int i=1,u,v;i<=m;i++) u=gi(),v=gi(),adde(u,v);

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

        if(!vis[i]) {

            V=E=cnt[0]=cnt[1]=cnt[2]=0;flag=0;dfs(i);

            if(flag) ans+=1ll*V*V;

            else if(!cnt[0]||!cnt[1]||!cnt[2]) ans+=E;

            else ans+=1ll*cnt[0]*cnt[1]+1ll*cnt[1]*cnt[2]+1ll*cnt[2]*cnt[0];

        }

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

    return 0;

}


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

#include<cstring>

#include<algorithm>

#define MAXN 100000

using namespace std;

typedef long long LL;

struct node

{

	int to,w;

	node *nxt;

}edges[MAXN*4+5];

node *ncnt,*Adj[MAXN+5];

int N,M;

int col[MAXN+5],cnt[3],edcnt=0;

bool legal=true;

void Init()

{

	ncnt=&edges[0];

	memset(col,-1,sizeof(col));

}

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

{

	node *p=++ncnt;

	p->to=v;

	p->w=w;

	p->nxt=Adj[u];

	Adj[u]=p;

}

void DFS(int u)

{

	cnt[col[u]]++;

	for(node *p=Adj[u];p!=NULL;p=p->nxt)

	{

		int v=p->to;

		int w=p->w;

		if(w==1)

			edcnt++;

		if(col[v]==-1)

		{

			col[v]=(col[u]+w)%3;

			DFS(v);

		}

		else if(col[v]!=(col[u]+w)%3)

			legal=false;

	}

}

int main()

{

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

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

	Init();

	scanf("%d %d",&N,&M);

	int u,v;

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

	{

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

		AddEdge(u,v,1);

		AddEdge(v,u,2);

	}

	LL ans=0;

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

		if(col[i]==-1)

		{

			edcnt=0;

			legal=true;

			memset(cnt,0,sizeof(cnt));

			col[i]=0;

			DFS(i);

			if(legal==false)

				ans+=(1LL*cnt[0]+1LL*cnt[1]+1LL*cnt[2])*(1LL*cnt[0]+1LL*cnt[1]+1LL*cnt[2]);

			else if(cnt[0]==0||cnt[1]==0||cnt[2]==0)

				ans+=1LL*edcnt;

			else if(legal==true)

				ans+=1LL*cnt[0]*cnt[1]+1LL*cnt[1]*cnt[2]+1LL*cnt[0]*cnt[2];

		}

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

	return 0;

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

#include<cstdio>

#include<cstring>

using namespace std;

 

int n,m,x,y;

int f[5],col[100005];

int tot=0,h[100005];

bool flag;

struct Edge{

	int x,dis,next;

}e[200005];

long long ans=0;

 

inline void add_edge(int x,int y,int z){

	e[++tot].x=y,e[tot].dis=z;

	e[tot].next=h[x],h[x]=tot;

}

 

void dfs(int x){

	f[col[x]]++;

	for(int i=h[x];i;i=e[i].next){

		f[3]+=e[i].dis==1;

		if(col[e[i].x]==-1){

			col[e[i].x]=(col[x]+e[i].dis)%3;

			dfs(e[i].x);

		}else{

			if(col[e[i].x]!=(col[x]+e[i].dis)%3)

				flag=true;

		}

	}

}

 

int main(){

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

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

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

		add_edge(x,y,1);

		add_edge(y,x,2);

	}

	memset(col,-1,sizeof(col));

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

	if(col[i]==-1){

		f[col[i]=0]=f[1]=f[2]=f[3]=flag=0;

		dfs(i);

		if(flag){

			int cnt=f[0]+f[1]+f[2];

			ans+=1LL*cnt*cnt;

		}else if(f[0]==0||f[1]==0||f[2]==0){

			ans+=f[3];

		}else{

			ans+=1LL*f[0]*f[1];

			ans+=1LL*f[1]*f[2];

			ans+=1LL*f[2]*f[0];

		}

	}

	printf("%lld",ans);

}


// Faster C++ solution for the same problem (measured speedup: 1.4047676662526918x):
#include<bits/stdc++.h>

#define ll long long

using namespace std;

int cnt,fst[200005],nxt[200005],to[200005],w[200005];

int n,m,col[200005],sum[3],res,snd;

ll ans;

bool vis[200005],fg;

void AddEdge(int u,int v,int c)

{

	to[++cnt]=v;

	nxt[cnt]=fst[u];

	fst[u]=cnt;

	w[cnt]=c;

}

int Calc(int x)

{

	return x>=3?x-3:(x<0?x+3:x);

}

void Dfs(int u)

{

	snd++;

	sum[col[u]]++;

	vis[u]=1;

	for(int i=fst[u];i;i=nxt[i])

	{

		int v=to[i];

		if(w[i]==1) res++;

		if(!vis[v])

		{

			col[v]=Calc(col[u]+w[i]);

			Dfs(v);

		}

		else if(col[v]!=Calc(col[u]+w[i])) fg=0;

	}

}

int main()

{

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

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

	{

		int x,y;

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

		AddEdge(x,y,1);

		AddEdge(y,x,-1);

	}

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

	{

		if(vis[i]) continue;

		memset(sum,0,sizeof(sum));

		res=snd=0;

		fg=1;

		Dfs(i);

		if(!fg) ans+=1ll*snd*snd;

		else if(sum[0] && sum[1] && sum[2]) ans+=1ll*sum[0]*sum[1]+1ll*sum[0]*sum[2]+1ll*sum[1]*sum[2];

		else ans+=1ll*res;

	}

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

	return 0;

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

#include<cstdio>

#include<cstring>

using namespace std;

 

int n,m,x,y;

int f[5],col[100005];

int tot=0,h[100005];

bool flag;

struct Edge{

	int x,dis,next;

}e[200005];

long long ans=0;

 

inline void add_edge(int x,int y,int z){

	e[++tot].x=y,e[tot].dis=z;

	e[tot].next=h[x],h[x]=tot;

}

 

void dfs(int x){

	f[col[x]]++;

	for(int i=h[x];i;i=e[i].next){

		f[3]+=e[i].dis==1;

		if(col[e[i].x]==-1){

			col[e[i].x]=(col[x]+e[i].dis)%3;

			dfs(e[i].x);

		}else{

			if(col[e[i].x]!=(col[x]+e[i].dis)%3)

				flag=true;

		}

	}

}

 

int main(){

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

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

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

		add_edge(x,y,1);

		add_edge(y,x,2);

	}

	memset(col,-1,sizeof(col));

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

	if(col[i]==-1){

		f[col[i]=0]=f[1]=f[2]=f[3]=flag=0;

		dfs(i);

		if(flag){

			int cnt=f[0]+f[1]+f[2];

			ans+=1LL*cnt*cnt;

		}else if(f[0]==0||f[1]==0||f[2]==0){

			ans+=f[3];

		}else{

			ans+=1LL*f[0]*f[1];

			ans+=1LL*f[1]*f[2];

			ans+=1LL*f[2]*f[0];

		}

	}

	printf("%lld",ans);

}


// Faster C++ solution for the same problem (measured speedup: 1.4045163526601236x):
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const int siz=1e6+1;

struct edge{

	int v,w,nxt;

}e[siz];



int n,m;

ll ans,cnt,_cnt;

ll ccnt[3];

int col[siz],head[siz];

bool flag;

bitset<siz> vis;



inline

int posi(int x){return ((x%3)+3)%3;}



void dfs(int now);

void add_edge(int u,int v,int w);



int main()

{

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

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

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

		add_edge(u,v,1);

		add_edge(v,u,-1);

	}

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

		if(vis[i])

			continue;

		memset(ccnt,0,sizeof ccnt);

		_cnt=cnt=0;

		flag=false;

		dfs(i);

		if(flag)

			ans+=cnt*cnt;

		else

			if(ccnt[0]>0&&ccnt[1]>0&&ccnt[2]>0)

				ans+=ccnt[0]*ccnt[1]+ccnt[1]*ccnt[2]+ccnt[0]*ccnt[2];

			else

				ans+=_cnt;

	}

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

}



void dfs(int now)

{

	cnt++;

	vis[now]=true;

	ccnt[col[now]]++;

	for(int i=head[now];i!=0;i=e[i].nxt){

		if(e[i].w==1)

			_cnt++;

		if(!vis[e[i].v]){

			col[e[i].v]=posi(col[now]+e[i].w);

			dfs(e[i].v);

		}

		else

			if(col[e[i].v]!=posi(col[now]+e[i].w))

				flag=true;

	}

}



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

{

	static int cnt;

	e[++cnt]={v,w,head[u]};

	head[u]=cnt;

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

#include <bits/stdc++.h>

#include <ext/pb_ds/assoc_container.hpp>

#include <ext/pb_ds/tree_policy.hpp>

 

using namespace std;

using namespace __gnu_pbds;

 

#define fi first

#define se second

#define mp make_pair

#define pb push_back

#define fbo find_by_order

#define ook order_of_key

 

typedef long long ll;

typedef pair<ll,ll> ii;

typedef vector<int> vi;

typedef long double ld; 

typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> pbds;

typedef set<int>::iterator sit;

typedef map<int,int>::iterator mit;

typedef vector<int>::iterator vit;

 

vi adj[100001];

int out[100001];

int in[100001];

vi type[100001];

int color[100001];

bool used2 = false;

int cnt = 0;

int c[3];

ll mm = 0;

ll tote = 0;

bool dfs(int u, int col)

{

	used2|=(in[u]&&out[u]);

	cnt++; c[col]++;

	color[u] = col;

	bool res = 1;

	mm += out[u];

	tote++;

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

	{

		int v = adj[u][i];

		int nw = (col+type[u][i])%3;

		if(color[v] == -1)

		{

			res&=dfs(v, nw);

		}

		else

		{

			if(color[v] != nw) res=false;

		}

	}

	return res;

}

 

int main()

{

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

	int n, m; cin>>n>>m;

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

	{

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

		adj[u].pb(v); adj[v].pb(u);

		type[u].pb(1); type[v].pb(2);

		out[u]++; in[v]++;

	}

	memset(color,-1,sizeof(color));

	ll res = 0;

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

	{

		if(color[i] == -1)

		{

			used2 = false; cnt = 0;

			memset(c,0,sizeof(c));

			mm = 0; tote = 0;

			bool ans=dfs(i, 0);

			//cerr<<c[0]<<' '<<c[1]<<' '<<c[2]<<' '<<mm<<'\n';

			if(ans)

			{

				if(used2)

				{

					for(int j = 0; j < 3; j++)

					{

						res += ll(c[j])*ll(c[(j+1)%3]);

					}

				}

				else

				{

					res += mm;

				}

			}

			else

			{	

				res += ll(tote)*ll(tote);

			}

		}

	}

	cout<<res<<'\n';

}


// Faster C++ solution for the same problem (measured speedup: 4.952671952029269x):
#include<bits/stdc++.h>

using namespace std;

#define ll long long

const int N=100005;

int n,m,cc,ff,sv,se,hd[N],vis[N],f[3];ll ans;

struct E{int v,nxt,w;}e[N*2];

inline void add(int u,int v,int w){e[++cc]=(E){v,hd[u],w};hd[u]=cc;}

void dfs(int x,int c)

{

	vis[x]=c;f[c]++;sv++;

	for(int i=hd[x];i;i=e[i].nxt)

	{

		int y=e[i].v;se+=(e[i].w==1);

		if(vis[y]==-1)dfs(y,(c+e[i].w)%3);

		else if(vis[y]!=(c+e[i].w)%3)ff=0;

	}

}

int main()

{

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

	for(int i=1,u,v;i<=m;i++)scanf("%d%d",&u,&v),add(u,v,1),add(v,u,2);

	memset(vis,-1,sizeof(vis));

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

	{

		ff=1;f[0]=f[1]=f[2]=0;sv=se=0;dfs(i,0);

		ans+=!ff?1ll*sv*sv:(!min(f[0],min(f[1],f[2]))?se:(1ll*f[0]*f[1]+1ll*f[1]*f[2]+1ll*f[2]*f[0]));

	}

	printf("%lld\n",ans);return 0;

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

#include <bits/stdc++.h>

#include <ext/pb_ds/assoc_container.hpp>

#include <ext/pb_ds/tree_policy.hpp>

 

using namespace std;

using namespace __gnu_pbds;

 

#define fi first

#define se second

#define mp make_pair

#define pb push_back

#define fbo find_by_order

#define ook order_of_key

 

typedef long long ll;

typedef pair<ll,ll> ii;

typedef vector<int> vi;

typedef long double ld; 

typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> pbds;

typedef set<int>::iterator sit;

typedef map<int,int>::iterator mit;

typedef vector<int>::iterator vit;

 

vi adj[100001];

int out[100001];

int in[100001];

vi type[100001];

int color[100001];

bool used2 = false;

int cnt = 0;

int c[3];

ll mm = 0;

ll tote = 0;

bool dfs(int u, int col)

{

	used2|=(in[u]&&out[u]);

	cnt++; c[col]++;

	color[u] = col;

	bool res = 1;

	mm += out[u];

	tote++;

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

	{

		int v = adj[u][i];

		int nw = (col+type[u][i])%3;

		if(color[v] == -1)

		{

			res&=dfs(v, nw);

		}

		else

		{

			if(color[v] != nw) res=false;

		}

	}

	return res;

}

 

int main()

{

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

	int n, m; cin>>n>>m;

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

	{

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

		adj[u].pb(v); adj[v].pb(u);

		type[u].pb(1); type[v].pb(2);

		out[u]++; in[v]++;

	}

	memset(color,-1,sizeof(color));

	ll res = 0;

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

	{

		if(color[i] == -1)

		{

			used2 = false; cnt = 0;

			memset(c,0,sizeof(c));

			mm = 0; tote = 0;

			bool ans=dfs(i, 0);

			//cerr<<c[0]<<' '<<c[1]<<' '<<c[2]<<' '<<mm<<'\n';

			if(ans)

			{

				if(used2)

				{

					for(int j = 0; j < 3; j++)

					{

						res += ll(c[j])*ll(c[(j+1)%3]);

					}

				}

				else

				{

					res += mm;

				}

			}

			else

			{	

				res += ll(tote)*ll(tote);

			}

		}

	}

	cout<<res<<'\n';

}


// Faster C++ solution for the same problem (measured speedup: 6.965492808119116x):
#include<bits/stdc++.h>

#define ll long long

using namespace std;

const int N=1e5+10;

int n,m,cnt,num1,num2,chk;

int head[N],vis[N],col[N],to[N<<1],nxt[N<<1],val[N<<1],stk[3];

ll ans;

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

	to[++cnt]=v,nxt[cnt]=head[u],val[cnt]=w,head[u]=cnt;

}

inline int tp(int x){ x=(x%3+3)%3; return x; }

void dfs(int u,int c){

	vis[u]=1,col[u]=c,stk[col[u]]++,num1++;

	for(int i=head[u];i;i=nxt[i]){

		int v=to[i];

		num2+=(val[i]==1);

		if(!vis[v]) dfs(v,tp(col[u]+val[i]));

		else if(col[v]!=tp(col[u]+val[i])) chk=1;

	}

}

int main(){

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

	for(int i=1;i<=m;i++) { int u,v; scanf("%d%d",&u,&v); add(u,v,1),add(v,u,-1); }

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

		if(vis[i]) continue; 

		num1=0,num2=0,chk=0; stk[0]=stk[1]=stk[2]=0; 

		dfs(i,0);

		if(chk) ans+=1ll*num1*num1;

		else if(stk[0] && stk[1] && stk[2]) ans+=1ll*stk[0]*stk[1]+1ll*stk[1]*stk[2]+1ll*stk[2]*stk[0];

		else ans+=num2;

	}

	printf("%lld",ans);

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

using namespace std;

#define ll long long

const int N=100005;

int n,m,cc,ff,sv,se,hd[N],vis[N],f[3];ll ans;

struct E{int v,nxt,w;}e[N*2];

inline void add(int u,int v,int w){e[++cc]=(E){v,hd[u],w};hd[u]=cc;}

void dfs(int x,int c)

{

	vis[x]=c;f[c]++;sv++;

	for(int i=hd[x];i;i=e[i].nxt)

	{

		int y=e[i].v;se+=(e[i].w==1);

		if(vis[y]==-1)dfs(y,(c+e[i].w)%3);

		else if(vis[y]!=(c+e[i].w)%3)ff=0;

	}

}

int main()

{

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

	for(int i=1,u,v;i<=m;i++)scanf("%d%d",&u,&v),add(u,v,1),add(v,u,2);

	memset(vis,-1,sizeof(vis));

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

	{

		ff=1;f[0]=f[1]=f[2]=0;sv=se=0;dfs(i,0);

		ans+=!ff?1ll*sv*sv:(!min(f[0],min(f[1],f[2]))?se:(1ll*f[0]*f[1]+1ll*f[1]*f[2]+1ll*f[2]*f[0]));

	}

	printf("%lld\n",ans);return 0;

}


// Faster C++ solution for the same problem (measured speedup: 1.4064111000255384x):
#include<bits/stdc++.h>

#define ll long long

using namespace std;

const int N=1e5+10;

int n,m,cnt,num1,num2,chk;

int head[N],vis[N],col[N],to[N<<1],nxt[N<<1],val[N<<1],stk[3];

ll ans;

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

	to[++cnt]=v,nxt[cnt]=head[u],val[cnt]=w,head[u]=cnt;

}

inline int tp(int x){ x=(x%3+3)%3; return x; }

void dfs(int u,int c){

	vis[u]=1,col[u]=c,stk[col[u]]++,num1++;

	for(int i=head[u];i;i=nxt[i]){

		int v=to[i];

		num2+=(val[i]==1);

		if(!vis[v]) dfs(v,tp(col[u]+val[i]));

		else if(col[v]!=tp(col[u]+val[i])) chk=1;

	}

}

int main(){

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

	for(int i=1;i<=m;i++) { int u,v; scanf("%d%d",&u,&v); add(u,v,1),add(v,u,-1); }

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

		if(vis[i]) continue; 

		num1=0,num2=0,chk=0; stk[0]=stk[1]=stk[2]=0; 

		dfs(i,0);

		if(chk) ans+=1ll*num1*num1;

		else if(stk[0] && stk[1] && stk[2]) ans+=1ll*stk[0]*stk[1]+1ll*stk[1]*stk[2]+1ll*stk[2]*stk[0];

		else ans+=num2;

	}

	printf("%lld",ans);

}