Tarjan算法

定義

在有向圖G中,如果兩個頂點間至少存在一條路徑,稱兩個頂點強連通(strongly connected)。如果有向圖G的每兩個頂點都強連通,稱G是一個強連通圖。非強連通圖有向圖的極大強連通子圖,稱爲強連通分量(strongly connected components)。

Tarjan算法可以用於求一張有向圖的最大強聯通分量

基本參數

對於一張有向圖

這裏寫圖片描述

上圖來自byvoid大牛

進行dfs搜索後會出現一棵dfs搜索樹

這裏寫圖片描述

1.time表示時間戳,表示這個節點是第幾個被訪問的
2.dfn表示u節點的時間戳
low數組表示以u爲根節點的子樹中的節點能訪問到的時間戳最小的節點的時間戳
開始時low[u]=dfn[u]
搜索完u所有相鄰的節點後
low[u]=min(low[u],low[v])(u能訪問v且v不在其他強連通分量中)
例如
low[1]=1
low[2]=1
low[4]=1

算法流程

tarjan(u)
{
DFN[u]=Low[u]=++Index // 爲節點u設定次序編號和Low初值
Stack.push(u) // 將節點u壓入棧中
for each (u, v) in E // 枚舉每一條邊
if (v is not visted) // 如果節點v未被訪問過
tarjan(v) // 繼續向下找
Low[u] = min(Low[u], Low[v])
else if (v in S) // 如果節點v還在棧內
Low[u] = min(Low[u], DFN[v])
if (DFN[u] == Low[u]) // 如果節點u是強連通分量的根
repeat
v = S.pop // 將v退棧,爲該強連通分量中一個頂點
print v
until (u== v)
}

轉自byvoid大牛

代碼:

const
  maxn=100;
var
  n,m,i,c,d,time,top:longint;
  relation:array[0..maxn,0..maxn] of boolean;
  dfn,low,stack:array[0..maxn] of longint;
  visit,instack:array[0..maxn] of boolean;
  function min(a,b:longint):longint;
begin
  if a<b
  then min:=a
  else min:=b;
end;
  procedure tarjan(u:longint);
var
  i:longint;
begin
  inc(time);
  low[u]:=time;
  dfn[u]:=time;
  visit[u]:=true;
  inc(top);
  stack[top]:=u;
  instack[u]:=true;
  for i:=1 to n do
    begin
      if relation[u,i]
      then begin
             if visit[i]=false
             then begin
                    tarjan(i);
                    low[u]:=min(low[u],low[i]);
                  end
             else if instack[i]
                  then low[u]:=min(low[u],low[i]);
           end;
    end;
   if low[u]=dfn[u]
   then begin
          while (top>0) and (stack[top]<>u) do
            begin
              write(stack[top],' ');
              instack[stack[top]]:=false;
              dec(top);
            end;
          write(stack[top]);
          instack[stack[top]]:=false;
          dec(top);
          writeln;
        end;
end;

begin
  read(n,m);
  fillchar(relation,sizeof(relation),false);
  for i:=1 to m do
    begin
      read(c,d);
      relation[c,d]:=true;
    end;
  time:=0;
  top:=0;
  fillchar(dfn,sizeof(dfn),0);
  fillchar(low,sizeof(low),0);
  fillchar(visit,sizeof(visit),false);
  fillchar(instack,sizeof(instack),false);
  tarjan(1);
end.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章