/*
1. 數(shù)組的初始化:當(dāng)首次搜索到點(diǎn)p時,Dfn與Low數(shù)組的值都為到該點(diǎn)的時間。
2. 堆棧:每搜索到一個點(diǎn),將它壓入棧頂。
3. 當(dāng)點(diǎn)p有與點(diǎn)p’相連時,如果此時(時間為dfn[p]時)p’不在棧中,p的low值為兩點(diǎn)的low值中較小的一個。
4. 當(dāng)點(diǎn)p有與點(diǎn)p’相連時,如果此時(時間為dfn[p]時)p’在棧中,p的low值為p的low值和p’的dfn值中較小的一個。
5. 每當(dāng)搜索到一個點(diǎn)經(jīng)過以上操作后(也就是子樹已經(jīng)全部遍歷)的low值等于dfn值,則將它以及在它之上的元素彈出棧。
這些出棧的元素組成一個強(qiáng)連通分量。
6. 繼續(xù)搜索(或許會更換搜索的起點(diǎn),因?yàn)檎麄€有向圖可能分為兩個不連通的部分),直到所有點(diǎn)被遍歷。
*/
void tarjan(int u) {
dfn[ u ] = low[ u ] = indeu ++;
S.push(u);
instack[ u ] = true;
for(int i = p[ u ]; i != -1; i = e[ i ].neut) {
int v = e[ i ].v;
if(dfn[ v ] == -1) {
tarjan(v);
low[ u ] = min(low[ u ], low[ v ]);
}
else if(instack[ v ])
low[ u ] = min(low[ u ], dfn[ v ]);
}
if(low[ u ] == dfn[ u ]) {
while(true) {
int tmp = S.top();
S.pop();
belong[ tmp ] = cnt;
instack[ tmp ] = false;
if(tmp == u) break;
}
cnt ++;
}
}