Tarjan強連通分量

2022-05-03 12:00:25 字數 2604 閱讀 4433

# 這是乙個漫(jian)長(nan)的過程

請大家耐心讀完,相信你一定能學會

首先來介紹一下強連通分量

神奇海螺指引你:

tarjan是基於迪法師(dfs)的一種演算法,可以說是一種流(du)批(liu)的操作,本蒟蒻苦哈哈的學了好幾天才學會強連通分量和縮點;

步入正軌:

圖中{6}是第乙個被發現的強連通分量,其次是{5},最後被發現的是{3,4,1,2}(順序無所謂)

tarjan演算法是解決強連通分量和縮點問題的一種比較常見的方法

接下來開始一步一步的

首先給你乙個圖(求其中的強連通分量)

在這裡我們假設從點1開始遍歷,並且將訪問的點壓入棧中

在進行操作之前,我們要明確tarjan中的兩個至關重要的陣列:dfn和low;

dfn[x]:表示這個點x幾次被遍歷到;

low[x]:表示點x或點x的子樹能夠追溯到的最早的棧中節點的次序號;

即low[x]=min;

其中next為x的子節點;

接下來,我們來一步一步的找;

第一遍從1直接一直遍歷到6,另訪問到的點的初始low和dfn都為num++;num為計數器;

但當我們遍歷到6是發現6沒有子節點了,所以low[6]=dfn[6]=4;發現乙個強連通分量{6},6出棧;

退回到5,low[5]=min(low[5],low[6]);

low[6]=4;而low[5]=dfn[5]=3;

所以low[5]=3;

low[5]=dfn[5];所以5也是乙個強連通分量;5出棧;

返回3發現3有子節點4,搜尋4,並且4入棧;發現4也有子節點,6已經為強連通分量且不再棧中,跳過;

遍歷1,發現一在棧中且已經被訪問過,那麼4值得被發現;

所以low[4]=min(low[4],dfn[1]);所以low[4]=1;

4遍歷完,又因為dfn[4]!=low[4],所以4不退站;回到3,low[3]=min(low[3],low[4]);

所以low[3]=1;3訪問完,又因為dfn[3]!=low[3],所以3不退站;

回到1,發現1還有子節點2,2入棧;發現2的子節點4已經被訪問且在棧中,所以low[2]=min(dfn[4],low[2]);

所以low[2]=5;訪問完2,回到一,發現low[1]=dfn[1];所以將棧中的所有點出棧,並且這些點為乙個強連通分量;

至此,所有點已經都被訪問,演算法結束。

時間複雜度為o(n+m);

下面插上**:

#include#include#include#include#include#define size 101

using namespacestd;

inline intread()

while(ch>='0'&&ch<='9')

return x*f;

}stackatack;

vectormap[size];

int a,b,c,d,num=0,low[size],dfn[size];

boolinst[size];

void tarjan(intnow)

else if(inst[next]==1)

}if(dfn[now]==low[now])

while(p!=now);

cout<

}}intmain()

memset(dfn,0,sizeof(dfn));

memset(inst,false,sizeof(inst));

for(int i=1;i<=a;++i)

return 0;

}

接下來,講一下縮點,

縮點基於強連通分量,在強連通分量的基礎上,稍微加一些操作即可。

縮點就是將所有在同乙個強連通分量中的點,壓進乙個點,然後再累加起每個點的權值,再每個點進行判斷,看他們所屬的強連通分量是否相同,如果不相同,則說明就是兩個不同的縮玩以後的點,我們就可以將他們存起來,存入乙個新圖。就是縮玩點以後的圖。

void tarjan(intnow)

else if(inst[next]==1)

}if(dfn[now]==low[now])

while(q!=now);}}

for(int i=1;i<=a;i++)}}

強連通分量 tarjan求強連通分量

雙dfs方法就是正dfs掃一遍,然後將邊反向dfs掃一遍。挑戰程式設計 上有說明。雙dfs 1 include 2 include 3 include 4 include 5 6using namespace std 7const int maxn 1e4 5 8 vector g maxn 圖的鄰...

強連通分量 tarjan

洛谷 p2812 校園網路 洛谷 p3387 縮點 include include include include include using namespace std struct arrbot 1100000 d 1100000 int head 20000 h 20000 stack 200...

強連通分量 tarjan

struct enodeedge maxm int p maxn ec void inserte int u,int v,int w int dfn maxn ctime,low maxn 時間戳,時間戳計數,祖先時間。int gid maxn gc 分量陣列,分量計數。bool ins maxn ...