Tarjan縮點


心魔

塔揚縮點是我長時間不想學的算法了。。。並查集能解決的事絕對不用並查集!!!,然而,隨着題目難度加深,我發現有些題目不得不用Tarjan解決,而且現對於並查集而言,思維量可以大大減少,所以這里寫下這篇博客,算個紀念吧

Tarjan是一位非常操蛋帥的人,發明了了大量的算法,什么並查集求LCA啊,什么SPLAY啊...不過最出名的還是他發明的縮點算法

正文

首先,什么叫縮點呢?我們需要先理解什么是強連通分量

強連通分量指的是:在一個有向圖中,強聯通分量的點可以互相到達,如在下圖中,一塊黃的就是一個強聯通分量

其實我不太說的清楚原理,直接上代碼注釋好了:

int DFN[maxn],LOW[maxn],index;//序號及環開頭的序號
int S[maxn],top;//手寫棧
bool ins[maxn];//是否進棧
int col[maxn],numc;//染色
void Tarjan(int u){
    DFN[u] = LOW[u] = ++index;
    S[++top] = u;//進棧
    ins[u] = true;
    for(int i = head[u];i;i = E[i].nxt){
        int v = E[i].v;
        if(!DFN[v]){
            Tarjan(v);
            LOW[u] = min(LOW[u],LOW[v]);//找爸爸(環開頭)最小的
            }
        else if(ins[v]){
            LOW[u] = min(LOW[u],DFN[v]);//判斷誰是爸爸
            }
        }
    if(DFN[u] == LOW[u]){//發現更新完一輪自己是爸爸
        numc++;
        while(S[top + 1] != u){
            col[S[top]] = numc;//出棧,染色
            ins[S[top--]] = false;
            }
        }
    }

關於Tarjan縮點的技巧

我們分兩種情況:

1.題目直接考Tarjan(重點)

這種情況一般是直接考縮點,通常和圖論的知識連用,而又以出度入度最為常見

首先如果原圖是一個無向又環圖,我們是沒辦法對其進行某些操作的(比如可以重復走一條路但是點權只加一次這類的),因為要重復訪問,所以DFS就毫無用武之地了,這時候我們就需要又Tarjan,在跑Tarjan的時候處理環的某些性質(如點權什么的),在建新圖,就可以在新圖上進行dp或者遍歷了。

2.題目考其他

這里不再贅述,Tarjan就是一個輔助作用,把有環圖縮為無環圖,就可以使用一些算法解決問題了

最近刷的Tarjan的題:

P2002 消息擴散 (與入度連用)

P2341 [HAOI2006]受歡迎的牛 (與出度連用)

P2746 [USACO5.3]校園網Network of Schools (入度和出度)

P2863 [USACO06JAN]牛的舞會The Cow Prom (圖論知識及對強聯通的理解)

P2835 刻錄光盤 (同上)

P3387 【模板】縮點


免責聲明!

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



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