tarjan模板pascal
//tarjan模板
var
i,n,m,x,y,total,so:longint;
h,dfn,low,ss,g1:array[1..10000]of longint;
bz:array[1..10000]of boolean;
z:array[0..10000]of longint;
g,l:array[1..30000]of longint;
procedure ad(x,y:longint); //前向星存边
begin
inc(so);g[so]:=y;l[so]:=h[x];h[x]:=so;
end;
function min(x,y:longint):longint;
begin
if x<y then exit(x)
else exit(y);
end;
procedure dg(x:longint);
var
i:longint;
begin
i:=h[x];
while i<>0 do
begin
if dfn[g[i]]=0 then //没有到过这个点
begin
inc(z[0]); //加入栈
z[z[0]]:=g[i];
bz[g[i]]:=true; //打上入栈标记
inc(total);dfn[g[i]]:=total;low[g[i]]:=total; //初始化
dg(g[i]);
low[x]:=min(low[x],low[g[i]]); //更新low(点在这颗树中的,最小的子树的根)
end
else if bz[g[i]]=true then low[x]:=min(low[x],low[g[i]]); //如果此点未出栈,则更新low
i:=l[i];
end;
if low[x]=dfn[x] then
begin
while z[z[0]]<>x do //未退到x
begin
bz[z[z[0]]]:=false; //去除标记
g1[z[z[0]-1]]:=z[z[0]]; //将前一个点连向当前点,这样在读取整个强联通分量时,
//可以从头开始往下跳,一直跳到结尾,这样可以省空间,存下整个图的强联通分量
//好像前向星的存边一样
z[z[0]]:=0; //抹除痕迹(可以删去)
dec(z[0]); //更新总数
inc(ss[x]); //更新强联通分量节点数
end;
bz[z[z[0]]]:=false;z[z[0]]:=0;inc(ss[x]);dec(z[0]);
end;
end;
begin
assign(input,'sf_tarjan.in');reset(input);
assign(output,'sf_tarjan.out');rewrite(output);
readln(n,m);
for i:=1 to m do
begin
readln(x,y);
ad(x,y);
end;
for i:=1 to n do
begin
if dfn[i]=0 then //没有到过这个点
begin
inc(z[0]);z[z[0]]:=i; //加入栈
bz[i]:=true; //打上入栈标记
inc(total); //更新总结点数
dfn[i]:=total;low[i]:=total; //初始化
dg(i);
end;
end;
close(input);
close(output);
end.