杞嚜錛?/p>
http://www.byvoid.com/blog/scc-tarjan/
鍦ㄦ湁鍚戝浘G涓紝濡傛灉涓や釜欏剁偣闂磋嚦灝戝瓨鍦ㄤ竴鏉¤礬寰勶紝縐頒袱涓《鐐?strong> 寮鴻繛閫?/strong> (strongly connected)銆傚鏋滄湁鍚戝浘G鐨勬瘡涓や釜欏剁偣閮藉己榪為氾紝縐癎鏄竴涓?strong> 寮鴻繛閫氬浘 銆傞潪寮鴻繛閫氬浘鏈夊悜鍥劇殑鏋佸ぇ寮鴻繛閫氬瓙鍥撅紝縐頒負 寮鴻繛閫氬垎閲?/strong> (strongly connected components)銆?/p>
涓嬪浘涓紝瀛愬浘{1,2,3,4}涓轟竴涓己榪為氬垎閲忥紝鍥犱負欏剁偣1,2,3,4涓や袱鍙揪銆倇5},{6}涔熷垎鍒槸涓や釜寮鴻繛閫氬垎閲忋?/p>
鐩存帴鏍規嵁瀹氫箟錛岀敤鍙屽悜閬嶅巻鍙栦氦闆嗙殑鏂規硶姹傚己榪為氬垎閲忥紝鏃墮棿澶嶆潅搴︿負O(N^2+M)銆傛洿濂界殑鏂規硶鏄疜osaraju綆楁硶鎴朤arjan綆楁硶錛屼袱鑰呯殑鏃墮棿澶嶆潅搴﹂兘鏄疧(N+M)銆傛湰鏂囦粙緇嶇殑鏄疶arjan綆楁硶銆?/p>
Tarjan綆楁硶鏄熀浜庡鍥炬繁搴︿紭鍏堟悳绱㈢殑綆楁硶錛屾瘡涓己榪為氬垎閲忎負鎼滅儲鏍戜腑鐨勪竴媯靛瓙鏍戙傛悳绱㈡椂錛屾妸褰撳墠鎼滅儲鏍戜腑鏈鐞嗙殑鑺傜偣鍔犲叆涓涓爢鏍堬紝鍥炴函鏃跺彲浠ュ垽鏂爤欏跺埌鏍堜腑鐨勮妭鐐規槸鍚︿負涓涓己榪為氬垎閲忋?/p>
瀹氫箟DFN(u)涓鴻妭鐐箄鎼滅儲鐨勬搴忕紪鍙?鏃墮棿鎴?錛孡ow(u)涓簎鎴杣鐨勫瓙鏍戣兘澶熻拷婧埌鐨勬渶鏃╃殑鏍堜腑鑺傜偣鐨勬搴忓彿銆傜敱瀹氫箟鍙互寰楀嚭錛?/p>
褰揇FN(u)=Low(u)鏃訛紝浠涓烘牴鐨勬悳绱㈠瓙鏍戜笂鎵鏈夎妭鐐規槸涓涓己榪為氬垎閲忋?/p>
綆楁硶浼唬鐮佸涓?/p>
鎺ヤ笅鏉ユ槸瀵圭畻娉曟祦紼嬬殑婕旂ず銆?/p>
浠庤妭鐐?寮濮婦FS錛屾妸閬嶅巻鍒扮殑鑺傜偣鍔犲叆鏍堜腑銆傛悳绱㈠埌鑺傜偣u=6鏃訛紝DFN[6]=LOW[6]錛屾壘鍒頒簡涓涓己榪為氬垎閲忋傞鏍堝埌u=v涓烘錛寋6}涓轟竴涓己榪為氬垎閲忋?/p>
榪斿洖鑺傜偣5錛屽彂鐜癉FN[5]=LOW[5]錛岄鏍堝悗{5}涓轟竴涓己榪為氬垎閲忋?/p>
榪斿洖鑺傜偣3錛岀戶緇悳绱㈠埌鑺傜偣4錛屾妸4鍔犲叆鍫嗘爤銆傚彂鐜拌妭鐐?鍚戣妭鐐?鏈夊悗鍚戣竟錛岃妭鐐?榪樺湪鏍堜腑錛屾墍浠OW[4]=1銆傝妭鐐?宸茬粡鍑烘爤錛?4,6)鏄í鍙夎竟錛岃繑鍥?錛?3,4)涓烘爲鏋濊竟錛屾墍浠OW[3]=LOW[4]=1銆?/p>
緇х畫鍥炲埌鑺傜偣1錛屾渶鍚庤闂妭鐐?銆傝闂竟(2,4)錛?榪樺湪鏍堜腑錛屾墍浠OW[2]=DFN[4]=5銆傝繑鍥?鍚庯紝鍙戠幇DFN[1]=LOW[1]錛屾妸鏍堜腑鑺傜偣鍏ㄩ儴鍙栧嚭錛岀粍鎴愪竴涓繛閫氬垎閲弡1,3,4,2}銆?/p>
鑷蟲錛岀畻娉曠粨鏉熴傜粡榪囪綆楁硶錛屾眰鍑轟簡鍥句腑鍏ㄩ儴鐨勪笁涓己榪為氬垎閲弡1,3,4,2},{5},{6}銆?/p>
鍙互鍙戠幇錛岃繍琛孴arjan綆楁硶鐨勮繃紼嬩腑錛屾瘡涓《鐐歸兘琚闂簡涓嬈★紝涓斿彧榪涘嚭浜嗕竴嬈″爢鏍堬紝姣忔潯杈逛篃鍙璁塊棶浜嗕竴嬈★紝鎵浠ヨ綆楁硶鐨勬椂闂村鏉傚害涓篛(N+M)銆?/p>
姹傛湁鍚戝浘鐨勫己榪為氬垎閲忚繕鏈変竴涓己鏈夊姏鐨勭畻娉曪紝涓篕osaraju綆楁硶銆侹osaraju鏄熀浜庡鏈夊悜鍥懼強鍏墮嗗浘涓ゆDFS鐨勬柟娉曪紝鍏舵椂闂村鏉傚害涔熸槸O(N+M)銆備笌Trajan綆楁硶鐩告瘮錛孠osaraju綆楁硶鍙兘浼氱◢寰洿鐩磋涓浜涖備絾鏄疶arjan鍙敤瀵瑰師鍥捐繘琛屼竴嬈FS錛屼笉鐢ㄥ緩绔嬮嗗浘錛屾洿綆媧併傚湪瀹為檯鐨勬祴璇曚腑錛孴arjan綆楁硶鐨勮繍琛屾晥鐜囦篃姣擪osaraju綆楁硶楂?0%宸﹀彸銆傛澶栵紝璇arjan綆楁硶涓?a target="_blank" style="color: #cc6600; text-decoration: none;">姹傛棤鍚戝浘鐨勫弻榪為氬垎閲?鍓茬偣銆佹ˉ)鐨凾arjan綆楁硶涔熸湁鐫寰堟繁鐨勮仈緋匯傚涔犺Tarjan綆楁硶錛屼篃鏈夊姪浜庢繁鍏ョ悊瑙f眰鍙岃繛閫氬垎閲忕殑Tarjan綆楁硶錛屼袱鑰呭彲浠ョ被姣斻佺粍鍚堢悊瑙c?/p>
姹傛湁鍚戝浘鐨勫己榪為氬垎閲忕殑Tarjan綆楁硶鏄互鍏跺彂鏄庤?a target="_blank" style="color: #cc6600; text-decoration: none;">Robert Tarjan鍛藉悕鐨勩俁obert Tarjan榪樺彂鏄庝簡姹?a target="_blank" style="color: #cc6600; text-decoration: none;">鍙岃繛閫氬垎閲?/a>鐨凾arjan綆楁硶錛屼互鍙婃眰鏈榪戝叕鍏辯鍏堢殑紱葷嚎Tarjan綆楁硶錛屽湪姝ゅTarjan琛ㄧず宕囬珮鐨勬暚鎰忋?/p>
闄勶細tarjan綆楁硶鐨凜++紼嬪簭 [Tarjan綆楁硶]
Low(u)=Min
{
DFN(u),
Low(v),(u,v)涓烘爲鏋濊竟錛寀涓簐鐨勭埗鑺傜偣
DFN(v),(u,v)涓烘寚鍚戞爤涓妭鐐圭殑鍚庡悜杈?闈炴í鍙夎竟)
}
tarjan(u)
{
DFN[u]=Low[u]=++Index // 涓鴻妭鐐箄璁懼畾嬈″簭緙栧彿鍜孡ow鍒濆?br> Stack.push(u) // 灝嗚妭鐐箄鍘嬪叆鏍堜腑
for each (u, v) in E // 鏋氫婦姣忎竴鏉¤竟
if (v is not visted) // 濡傛灉鑺傜偣v鏈璁塊棶榪?br> tarjan(v) // 緇х畫鍚戜笅鎵?br> 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鏄己榪為氬垎閲忕殑鏍?br> repeat
v = S.pop // 灝唙閫鏍堬紝涓鴻寮鴻繛閫氬垎閲忎腑涓涓《鐐?br> print v
until (u== v)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
void tarjan(int i)
{
int j;
DFN[i]=LOW[i]=++Dindex;
instack[i]=true;
Stap[++Stop]=i;
for (edge *e=V[i];e;e=e->next)
{
j=e->t;
if (!DFN[j])
{
tarjan(j);
if (LOW[j]<LOW[i])
LOW[i]=LOW[j];
}
else if (instack[j] && DFN[j]<LOW[i])
LOW[i]=DFN[j];
}
if (DFN[i]==LOW[i])
{
Bcnt++;
do
{
j=Stap[Stop--];
instack[j]=false;
Belong[j]=Bcnt;
}
while (j!=i);
}
}
void solve()
{
int i;
Stop=Bcnt=Dindex=0;
memset(DFN,0,sizeof(DFN));
for (i=1;i<=N;i++)
if (!DFN[i])
tarjan(i);
}
]]>