Tarjan


一、Tarjan算法求LCA

二、Tarjan算法求強連通分量【棧里存點---------每個點都屬於一個強連通分量】

(着重理解一下第11行的else if語句:dfn[ i ]!=0 且 instk[i]==0的點一定已經是另一個強連通分量里面的點了,所以就不用考慮了,所以用else if(instk[ i ])來判斷是不是已經是別的強連通分量里的點了,如果不是,則是當前點的祖先,可以用來更新low[ u ],這也是強連通分量的更新low[ u ]的精髓。)

 1 void Tarjan(int u) {
 2     dfn[u] = low[u] = ++tim;
 3     in_stk[u] = 1;
 4     stk[tp++] = u;
 5     for (int i = head[u]; i != -1; i = e[i].next) {
 6         int v = e[i].to;
 7         if (!dfn[v]) {
 8             Tarjan(v);
 9             if (low[v] < low[u])low[u] = low[v];
10         }
11         else if (in_stk[v]) {
12             if (low[v] < low[u])low[u] = low[v];//這里使用dfn[v]和low[v]都可以
13         }
14     }
15     if (dfn[u] == low[u]) {
16         scc_cnt++;
17         do {
18             tp--;
19             int tt = stk[tp];
20             col[tt] = scc_cnt;
21             in_stk[tt] = 0;
22             vc[scc_cnt].push_back(tt);
23         } while (stk[tp] != u);
24     }
25 }

 

三、Tarjan算法求雙連通分量【棧里存邊------每條邊都屬於一個點雙連通分量】

(由於是無向圖,這里需要注意的是不能重復訪問邊,用else if(dfn[ u ]>dfn[ v ]&&v!=fa)來防止重復訪問)

 1 void Tarjan(int u, int fa) {
 2     dfn[u] = low[u] = ++tim;
 3     int child = 0;
 4     for (int i = head[u]; i != -1; i = e[i].next) {
 5         int v = e[i].to;
 6         struct edge e1;
 7         e1.fr = u; e1.to = v;
 8         if (!dfn[v]) {
 9             stk.push(e1);
10             child++;
11             Tarjan(v);
12             if (low[v] >= dfn[u]) {
13                 iscut[u] = true;
14                 bcc_cnt++; bcc[bcc_cnt].clear();
15                 do {
16                     struct edge e2 = stk.top(); stk.pop();
17                     if (col[e2.fr]!=bcc_cnt) {
18                         bcc[bcc_cnt].push_back(e2.fr);
19                         col[e2.fr] = bcc_cnt;
20                     }
21                     if (col[e2.to]!=bcc_cnt) {
22                         bcc[bcc_cnt].push_back(e2.to);
23                         col[e2.to] = bcc_cnt;
24                     }
25                 } while (e2.fr != u || e2.to != v);
26             }
27         }
28         else if (dfn[v] < dfn[u] && v != fa) {
29             stk.push(e1);
30             low[u] = min(low[u], dfn[v]);//注意這里必須是dfn[v],而不能是low[v],因為low[v]很可能在另一個雙連通分量已經被更新,這個時候用會出錯
31         }
32         if (fa < 0 && chile == 1)iscut[u] = false;
33     }
34 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM