Tarjan演算法 學習筆記

2022-03-26 10:51:40 字數 2778 閱讀 1598

tarjan演算法一般用於有向圖裡強連通分量的縮點。

強連通分量:有向圖裡能夠互相到達的點的集合。(大概是這麼個意思,自己意會)

因為能夠互相到達,所以巨集觀上我們可以把它們看成乙個點,邊權也相應的加起來即可。

下面是tarjan過程的**解釋:

我們開兩個陣列,分別為dfn和low。dfn表示此點的時間戳,low表示最早的時間戳。(即進入某乙個環最早的時間戳)

遇到乙個沒有記錄過的點,就把它扔到棧裡,不停dfs,直到dfn==low,即某乙個環已經遍歷完了,我們就彈棧,將這乙個環合併。

**如下:

void tarjan(int

now)

if (dfn[now]==low[now])

}}

配合拓撲排序,一張新的有向無環圖就構造了出來。

【模板】 縮點

給定乙個含有n個點m條邊的有向圖每個點有乙個權值,求一條路徑,使路徑經過的點權值之和最大。你只需要求出這個權值和。

允許多次經過一條邊或者乙個點,但是,重複經過的點,權值只計算一次。

第一行兩個整數,為$n$,$m$。

第二行到第$m+1$行有每行有3個整數,分別為$u,v,d$,表示$u\rightarrow v$有一條長度為$d$的邊。

輸出格式:一行結果。

tarjan模板題,只不過加了一點小dp,記憶化搜尋即可。注意的地方就是拓撲排序後的重新建圖。

#includeusing

namespace

std;

const

int maxn=200005

;int

cnt,dfn[maxn],vis[maxn],low[maxn];

intf[maxn],sum[maxn],ans;

int jishu,head[500005

];int

top,st[maxn],pos[maxn],tot;

intn,m,x[maxn],y[maxn],val[maxn];

struct

node

edge[

500005

];inline

intread()

while(isdigit(ch))

return x*f;

}inline

void add(int

from,int

to)void tarjan(int

now)

if (dfn[now]==low[now])

}}void search(int

x) f[x]+=maxx;

}void

clear()

intmain()

for (int i=1;i<=n;i++) if (!dfn[i]) tarjan(i);

clear();

for (int i=1;i<=m;i++) if (pos[x[i]]!=pos[y[i]]) add(pos[x[i]],pos[y[i]]);

for (int i=1;i<=n;i++) search(i),ans=max(ans,f[i]);

printf(

"%d\n

",ans);

return0;

}

另,如果是無向圖縮點,一定要加上這句話:

if (edge[i].to==fa) continue;

【模板】割點

給定乙個含有n個點m條邊的無向圖,求圖的割點。

割點是指去掉這個點整個圖便不連通的點。

我們可以同樣用tarjan演算法,建立一顆搜尋樹。

如果此點為根節點,則判斷是否有》=2棵子樹。如果存在,那麼此點為割點。

對於非根節點,如果low[v]>=dfn[u]($u\rightarrow v$)那麼u點為割點(因為從u點開始無論怎麼走都不可能回到原來的點了)。

思路還是比較清晰的,直接放**:

#includeusing

namespace

std;

const

int maxn=200005

;int head[500005

],jishu;

intdfn[maxn],low[maxn],cnt;

intn,m,ans;

bool

cut[maxn];

struct

node

edge[

500005

];inline

intread()

while(isdigit(ch))

return x*f;

}inline

void add(int

from,int

to)void tarjan(int now,int

fa) low[now]=min(low[now],dfn[to]);

}if (child>=2&&now==fa) cut[now]=1;}

intmain()

for (int i=1;i<=n;i++) if (!dfn[i]) tarjan(i,i);

for (int i=1;i<=n;i++) if (cut[i]) ans++;

printf(

"%d\n

",ans);

for (int i=1;i<=n;i++) if (cut[i]) printf("

%d "

,i);

return0;

}

演算法學習筆記 Tarjan演算法

演算法資料結構 三個步驟完成強連通分量分解的kosaraju演算法 我們來思考乙個問題,對於強連通分量分解的演算法來說,它的核心原理是什麼?如果你看過我們之前的文章,那麼這個問題對你來說應該不難回答。既然是強連通分量,意味著分量當中每個點都可以互相連通。所以我們很容易可以想到,我們可以從乙個點出發,...

演算法 學習筆記

1.輸入輸出演算法至少有乙個或多個輸出 2.有窮性 3.確定性 4.可行性 1.正確性a.演算法程式沒有語法錯誤 b.演算法程式對於合法的輸入資料能夠產生滿足要求的輸出結果 c.演算法程式對於非法的輸入資料能夠得出滿足規格說明的結果 d.演算法對於精心選擇的,甚至刁難的測試資料都有滿足要求的輸出結果...

演算法學習筆記

複雜度分析 1.只關注迴圈次數最多的一行 2.總複雜度等於量級最大 的複雜度 3.巢狀 的複雜度等於巢狀 內外複雜度的乘積 單鏈表結構和順序儲存結構的優缺點 儲存分配方式 時間效能 空間效能 單鏈表結構 用一組任意的儲存單元存放線性表元素 查詢 o n 插入和刪除 找到某位置的指標後,插入和刪除的時...