// 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.392952143552806x):
#include<bits/stdc++.h>

clock_t t=clock();

namespace IO

{

	using namespace std;

	char buf[1<<22],Out[1<<22],*p1=buf,*p2=buf;

	int p3=-1,f=0;

	inline void file()

	{

		#ifdef NTFOrz

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

		#endif

	}

	inline char getchar()

	{

		return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;

	}

	inline void flush(){fwrite(Out,1,p3+1,stdout),p3=-1;}

	inline void check(){if (p3>(1<<21)) flush();}

	inline void putchar(char a){Out[++p3]=a;check();}

	inline void putline(string s)

	{

		int tmp=p3;

		while (p3-tmp<s.size()) putchar(s[p3-tmp]);

		putchar('\n');

	}

	inline char gc()

	{

		char c=getchar();

		while (!c||c=='\n'||c==' ') c=getchar();

		return c;

	}

	inline void chktime()

	{

		#ifdef NTFOrz

		printf("%dms\n",clock()-t);

		#endif

	}

}

namespace my_std

{

	using namespace std;

	#define getchar IO::getchar

	#define putchar IO::putchar

    #define Re register

    #define rep(i,a,b) for (Re int i=(a);i<=(b);i++)

    #define drep(i,a,b) for (Re int i=(a);i>=(b);i--)

    #define repv(i,v) for (Re int i=0;i<v.size();i++)

    #define go(u) for (Re int i=head[(u)];i;i=e[i].nxt)

    #define writesp(x) write(x),putchar(' '),IO::check()

    #define writeln(x) write(x),putchar('\n'),IO::check()

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

    #define pb push_back

    #define fir first

    #define sec second

    #define MP make_pair

    typedef long long ll;

    typedef unsigned long long ull;

    typedef pair<int,int> pii;

    const int INF=0x7fffffff;

    inline int read()

    {

        ll sum=0,f=0;char c=getchar();

        while (!isdigit(c)) f|=(c=='-'),c=getchar();

        while (isdigit(c)) sum=(sum<<1)+(sum<<3)+(c^48),c=getchar();

        return f?-sum:sum;

    }

    void write(int k)

    {

        if (k<0) putchar('-'),k=-k;

        if (k>=10) write(k/10);

        putchar(k%10+48);

    }

	#define templ template<typename T>

    templ inline void chkmax(T &x,T y){if (x<y) x=y;}

    templ inline void chkmin(T &x,T y){if (x>y) x=y;}

}

using namespace my_std;

const int N=100010;

int n,m,ecnt,head[N],siz,flag,path,cnt[5],col[N];

ll ans;

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

inline void add_edge(int u,int v,int w){e[++ecnt].to=v,e[ecnt].nxt=head[u],e[ecnt].dis=w,head[u]=ecnt;}

inline int add(int x,int y){return x+y>=3?x+y-3:x+y;}

void dfs(int u)

{

	siz++,cnt[col[u]]++;

	go(u)

	{

		int v=e[i].to;

		path+=(e[i].dis==1);

		if (col[v]==INF)

		{

			col[v]=add(col[u],e[i].dis);

			dfs(v);

		}

		else if (col[v]!=add(col[u],e[i].dis)) flag=1;

	}

}

int main()

{

	IO::file();

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

	rep(i,1,n) col[i]=INF;

	rep(i,1,m)

	{

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

		add_edge(u,v,1),add_edge(v,u,2);

	}

	rep(i,1,n) if (col[i]==INF)

	{

		siz=flag=path=col[i]=0;

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

		dfs(i);

		if (!flag)

		{

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

			else ans+=path;

		}

		else ans+=1ll*siz*siz;

	}

	cout<<ans<<endl;

	IO::flush();

	IO::chktime();

	return 0;

}