http://kmplayer.iteye.com/blog/604532
var
next,last,z,tov,low,dfn:array[1..1000000] of longint;
vis,zz:array[1..1000000] of boolean;
tot,n,m,i,x,y,time,zd,ans:longint;
procedure insert(x,y:longint);
begin
inc(tot);
tov[tot]:=y;
next[tot]:=last[x];
last[x]:=tot;
end;
function min(x,y:longint):longint;
begin
if x<y then exit(x);
exit(y);
end;
procedure tarjan(x:longint);
var
i,y,t:longint;
begin
inc(time);
dfn[x]:=time;
low[x]:=time;
inc(zd);
z[zd]:=x;
zz[x]:=true;
i:=last[x];
while i<>0 do
begin
y:=tov[i];
if vis[y] then
begin
vis[y]:=false;
tarjan(y);
low[x]:=min(low[x],low[y]);
end
else
if zz[y] then low[x]:=min(low[x],dfn[y]);
i:=next[i];
end;
if dfn[x]=low[x] then
begin
t:=0;
repeat
zz[z[zd]]:=false;
inc(t);
dec(zd);
until z[zd+1]=x;
inc(ans,t*(t-1)div 2);
end;
end;
begin
readln(n,m);
for i:=1 to m do
begin
readln(x,y);
insert(x,y);
end;
fillchar(vis,sizeof(vis),true);
for i:=1 to n do
if vis[i] then
begin
vis[i]:=false;
tarjan(i);
end;
writeln(ans);
end.