tarjan演算法一般用於有向圖裡強連通分量的縮點。
強連通分量:有向圖裡能夠互相到達的點的集合。(大概是這麼個意思,自己意會)
因為能夠互相到達,所以巨集觀上我們可以把它們看成乙個點,邊權也相應的加起來即可。
下面是tarjan過程的**解釋:
我們開兩個陣列,分別為dfn和low。dfn表示此點的時間戳,low表示最早的時間戳。(即進入某乙個環最早的時間戳)
遇到乙個沒有記錄過的點,就把它扔到棧裡,不停dfs,直到dfn==low,即某乙個環已經遍歷完了,我們就彈棧,將這乙個環合併。
**如下:
void tarjan(intnow)
if (dfn[now]==low[now])
}}
配合拓撲排序,一張新的有向無環圖就構造了出來。
【模板】 縮點
給定乙個含有n個點m條邊的有向圖每個點有乙個權值,求一條路徑,使路徑經過的點權值之和最大。你只需要求出這個權值和。
允許多次經過一條邊或者乙個點,但是,重複經過的點,權值只計算一次。
第一行兩個整數,為$n$,$m$。
第二行到第$m+1$行有每行有3個整數,分別為$u,v,d$,表示$u\rightarrow v$有一條長度為$d$的邊。
輸出格式:一行結果。
tarjan模板題,只不過加了一點小dp,記憶化搜尋即可。注意的地方就是拓撲排序後的重新建圖。
#includeusingnamespace
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點開始無論怎麼走都不可能回到原來的點了)。
思路還是比較清晰的,直接放**:
#includeusingnamespace
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 插入和刪除 找到某位置的指標後,插入和刪除的時...