参考:http://blog.sina.com.cn/s/blog_69a101130100k1cm.html
tarjan算法在强连通分量分离中运用很广,书写简单,并且可以拓展到图的割点,割边上,十分强大
具体思路:令dfn【u】表示当前点的时间戳
low【u】表示当前点所能到达的点的时间戳中最小的一个
到达点u时,将其入栈
拓展点u后代
当且仅当dfn【u】=low【u】时,栈顶元素全部出栈,此时出栈的元素即为一个强连通分量。
我写的程序:
type
point=^node;
node=record
v:longint;
next:point;
end;
var
instack:array[0..100000]of boolean;
time,top,n,ans,i,x,y:longint;
low,stack,dfn:array[0..100000]of longint;
a:array[0..100000]of point;
function min(a,b:longint):longint;
begin
if a<b then exit(a);
exit(b);
end;
procedure tarjan(u:longint);
var
p:point;
v:longint;
begin
time:=time+1;
low[u]:=time;dfn[u]:=time;
stack[top]:=u;
instack[u]:=true;
top:=top+1;
p:=a[u];
while p<>nil do
begin
if dfn[p^.v]=0 then
begin
tarjan(p^.v);
low[u]:=min(low[u],low[p^.v]);
end
else if instack[p^.v] then low[u]:=min(low[u],dfn[p^.v]);
p:=p^.next;
end;
if low[u]=dfn[u] then
begin
ans:=ans+1;
writeln('Case #',ans,':');
repeat
top:=top-1;v:=stack[top];
write(v,' ');
instack[v]:=false;
until u=v;
writeln;
end;
end;
procedure build(x,y:longint);
var
p:point;
begin
new(p);
p^.v:=y;
p^.next:=a[x];
a[x]:=p;
end;
begin
readln(n);
top:=1;
for i:=1 to n do
begin
readLn(x,y);
build(x,y);
end;
tarjan(1);
end.