由于手残的问题,之前先把第三题给发了,这是我的Tarjan第二题
题目大意:题目的原意懒得翻译了,大概就是说有N个牛,围在一水池边,它们用绳子互相绑着(有方向的)。如果绳子的方向一致,它们就能顺时针转,问有多少组牛可以跳舞
思路:还是先画图,画完之后很快可以明白又是一道水题:读入n,m(2<=n<=10000,2<=m<=50000),其中有n个点,m条边,下面每行给出一条边的信息,求出强连通块内点数大于等于2的块的数量(也就意味着不用存储,遍历一次统计一下就好了)。
没啥需要注意的,懒的话直接把2186的代码改一下直接可以过,但是初学还是多打一次增加以下熟练度,没有1A真觉得对不起自己和老师
type
rec=record
next,t:longint;
end;
var
f,v:array[1..10010] of boolean;
edge:array[1..50010] of rec;
head,low,dfn,stack:array[1..10010] of longint;
n,m,x,y,ans,deep,top,t,tmp,sum,i:longint;
function min(a,b:integer):longint;
begin
if a<b then exit(a) else exit(b);
end;
procedure pop(k:longint);
begin
ans:=0; //统计点数
while stack[top+1]<>k do
begin
inc(ans);
f[stack[top]]:=false;
dec(top);
end;
if ans>=2 then inc(sum); //都说了不用存的
end;
procedure dfs(k:longint);
var
tmp:longint;
begin
inc(deep);
low[k]:=deep; dfn[k]:=deep; v[k]:=true;
inc(top);
stack[top]:=k; f[k]:=true;
tmp:=head[k];
while tmp<>-1 do
begin
if v[edge[tmp].t]=false then
begin
dfs(edge[tmp].t);
low[k]:=min(low[k],low[edge[tmp].t]);
end
else
if f[edge[tmp].t] then low[k]:=min(low[k],dfn[edge[tmp].t]);
tmp:=edge[tmp].next;
end;
if dfn[k]=low[k] then pop(k);
end;
begin
readln(n,m);
for i:=1 to n do head[i]:=-1; fillchar(edge,sizeof(edge),0); //初始化
for i:=1 to m do
begin
readln(x,y);
edge[i].t:=y;
edge[i].next:=head[x];
head[x]:=i;
end;
fillchar(v,sizeof(v),false); fillchar(f,sizeof(f),false);
for i:=1 to n do
if v[i]=false then dfs(i); //tarjan
writeln(sum);
end.