您的位置:首页 > 其它

求强连通分量之tarjan算法

2015-10-18 10:51 429 查看

tarjan算法优点在于时间复杂度的降低,由于每条边与每个顶点均遍历一次,故时间复杂度为O(n+m)。

关键字:深度优先搜索,栈(每个强连通分量相当于一个搜索树的子树,其顶点在栈中是连续的)

搜索时,把当前搜索树中未处理的节点加入一个堆栈,回溯时可以判断栈顶到栈中的节点是否为一个强连通分量。

有篇很清楚的讲解文章:https://www.byvoid.com/blog/scc-tarjan/

pascal程序:

var
side:array[0..100,0..100] of boolean;          //点x与点y是否连边(邻接矩阵)
stack,dfn,low:array[0..100] of longint;        //stack数组表示栈,dfn(u)为节点u搜索的次序编号,low(u)为u或u的子树能够追溯到的最早的栈中节点的次序号
v:array[0..100] of boolean;                    //节点x是否在栈中
deep,top,n,m,i,x,y:longint;                    //top是指栈的高度

function min(a,b:longint):longint;
begin
if a<b then min:=a else min:=b;
end;

procedure tarjan(x:longint);
var
i:longint;
begin
inc(deep);                    //初始赋值
dfn[x]:=deep;low[x]:=deep;    //将x加入栈中
inc(top);stack[top]:=x;
v[x]:=true;
for i:=1 to n do
if side[x,i] then begin
if dfn[i]=0 then begin   //节点i没被遍历过(很重要!)
tarjan(i);
low[x]:=min(low[x],low[i]);
end
else
if v[i] then low[x]:=min(low[x],dfn[i]);
end;
if dfn[x]=low[x] then begin   //当dfn(u)=low(u)时,以u为根的搜索子树上所有节点是一个强连通分量。
repeat
v[stack[top]]:=false;
write(stack[top],' ');   //从上至节点x一一出站
dec(top);
until stack[top+1]=x;
writeln;
end;
end;

begin
fillchar(side,sizeof(side),false);
readln(n,m);
for i:=1 to m do begin
readln(x,y);
side[x,y]:=true;
end;
top:=0;
deep:=0;
for i:=1 to n do
if dfn[i]=0 then tarjan(i);
readln;
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息