1. 程式人生 > >tarjan(縮點)

tarjan(縮點)

int span show 代碼 傳遞 喜歡 過程 pan 數據

剛做了兩道tarjan縮點的題,新學的算法總結一下。

推薦題:(難度單調遞增)

[HAOI2006]受歡迎的牛

[USACO5.3]校園網Network of Schools

間諜網絡

[APIO2009]搶掠計劃

這裏不教tarjan,要學的找別的博客吧。

總結:tarjan 簡單來說 算法過程 就是找環或單獨的點,這就可以構成強聯通分量。

代碼如下:

void tarjan(int u){
    low[u]=dfn[u]=++cnt;
    stk[++top]=u;
    vis[u]=1;
    for(register int i=head[u];i;i=edge[i].next){
        
int v=edge[i].to; if(!dfn[v]){ tarjan(v); low[u]=min(low[u],low[v]); } else if(vis[v]) low[u]=min(low[u],dfn[v]); } if(dfn[u]==low[u]){ co[u]=++col; vis[u]=0; while(stk[top]!=u){ vis[stk[top]]
=0; co[stk[top]]=col; top--; } top--; } }

縮點也很簡單,根據col重新建個圖就行了。

tarjan縮點題的一些特征和突破口:

1.一般tarjan縮點的題會給你具有傳遞性的圖,利用傳遞性可以省略掉一些點,例如:如果a喜歡b,b喜歡c,那麽a就喜歡c。假設c又喜歡a,這就可以構成一個強連通分量,縮點即可,沒錯,這就是“受歡迎的牛”。

2.點的入度和出度是很重要的,很多題就圍繞這這個東西去變式,關註點的入度和出度,往往會找到突破口。

3.有的題需要記錄一些強連通分量內的數據

(1)可以在同一強連通分量中的點出棧的過程中更新,這樣比較方便簡單。
(2)也可以在主程序中再次for循環去更新,那樣就比較麻煩了,時間復雜度和空間復雜度都得增加,然而我第一次打這類題就是這麽操作的,代碼90行。

反思:還是理解不夠深,我的tarjan總是打錯一點,然後又去修改,還是得多模擬一下tarjan縮點的過程。

tarjan(縮點)