Tarjan演算法的練習

2021-09-16 14:19:58 字數 3039 閱讀 6808

基本介紹:

tarjan演算法其實就是一種帶技巧的dfs,比普通的dfs多了兩個標記:dfn和low,實質上還是一種dfs。

tarjan演算法能做什麼?

求有向圖的強連通分量

求無向圖的割點

求無向圖的橋(割邊)

求lca(最近公共祖先)

網上有很多的tarjan演算法詳解,這裡就不重複造輪子了。剛學tarjan演算法的時候覺得很神奇,花了很長時間去消化,但是不去用慢慢就又忘了,所以這裡貼出一些tarjan演算法的練習題去鞏固。

poj - 1236 求強連通分量的練習

題目鏈結

題意是給你一張有向圖,資訊會沿著有向圖的路徑傳播,

1.問要把初始資訊給幾個點才能傳遍網路

2.問新增幾條有向邊可以讓整張圖強連通

題解:強連通縮點之後圖變成dag,入度為0的點的數量為第一問答案,入度為0的點和出度為0的點的數量的最大值為第二問答案。

ac**:

#include#include#include#include#include#includeusing namespace std;

const int maxn = 233;

vectorg[maxn];

struct nodee[maxn*maxn];

int cnt;

int head[maxn];

void add(int u,int v)

int in[maxn],out[maxn];

int n;

void init()

u++; }}

int id[maxn];

int dfn[maxn],low[maxn];

int index;

int scc;

stacks;

int inq[maxn];

void tarjan(int u)

else if(inq[v]) low[u] = min(low[u],dfn[v]);

} if(low[u] == dfn[u])

s.pop();

id[u] = scc;

inq[u] = 0; }}

void sol()

for(int i = 0;i < cnt;++i)

int a = 0,b = 0;

for(int i = 1;i <= scc;++i)

cout題目鏈結

題意:一棵樹,邊權為1,查詢兩個結點之間的距離,多次查詢

題解:先dfs求各點到根的距離,對於查詢u,v,dis[u] + dis[v] - 2*dis[lca(u,v)]即為答案。

ac**:

#include#include#define pb push_back

using namespace std;

typedef pairp;

const int maxn = 4e4 + 50;

int n,m;

vectorg[maxn],q[maxn];

vectorquery;

int lca[maxn];

void init()

for(int i = 0; i < m;++i)

}int vis[maxn];

int fa[maxn];

int fnd(int x)

int dis[maxn];

void tarjan(int u,int w)

for(int j = 0;j < q[u].size();++j)

}void sol()

}int main()

hdu4738 橋(割邊)的練習

題目鏈結

題意:給一張無向圖,求所有橋中權值最小的乙個

題解:tarjan求橋,注意求出權值為0的話要輸出1,因為要有人運炸彈

#include#includeusing namespace std;

const int maxn = 1e3 + 50;

const int inf = 0x3f3f3f3f;

int n,m;

struct nodee[maxn*maxn];

int cnt = 0;

int head[maxn];

void add(int u,int v,int w)

void init()

}int dfn[maxn],low[maxn];

int index;

int ans = inf;

void tarjan(int u,int id)

else if(i != (id^1)) low[u] = min(low[u],dfn[v]); }}

void sol()e[maxn*5];

int cnt = 0;

int head[maxn];

void add(int u,int v)

void init()

}int dfn[maxn],low[maxn],pre[maxn],inq[maxn],isgb[maxn];

int fa[maxn];// 用來縮點

int fnd(int x)

int index;

int ans = 0;

void tarjan(int u,int id)

else if(inq[v]) low[u] = min(low[u],dfn[v]);

} inq[u] = 0;

}void link(int u,int v)

void lca(int u,int v)

else

if(fnd(u) == fnd(v)) break; }}

int ca = 0;

void sol()

printf("%d\n",ans);

} printf("\n");

}int main()

}

這題求lca部分網上很多寫法是先預處理所有點的深度,操作u和v的時候先提公升到同乙個深度再一起往上跑,但是其實我們可以利用dfn的性質直接找到lca。

幾道題 Tarjan練習

tarjan的教程網上都有 cogs8 備用交換機 7 1 2 2 3 2 4 3 4 4 5 4 6 4 7 5 6 6 7輸出檔名 gd.out 2 2 4求割點 include include include include include using namespace std struct...

Tarjan演算法的改裝

tarjan演算法是用來解決強連通分量問題的常用演算法,演算法是基於深度優先搜尋的架構,在深度優先搜尋的過程中,迭代地求出各個節點u的標值lowlink u 其中 lowlink u min dfn u dfn w 在這裡,w是從u和u的後代點出發用一條後向弧和橫叉弧所能達到的同乙個強連通分支的節點...

tarjan演算法詳解

參考 tarjan演算法在強連通分量分離中運用很廣,書寫簡單,並且可以拓展到圖的割點,割邊上,十分強大 具體思路 令dfn u 表示當前點的時間戳 low u 表示當前點所能到達的點的時間戳中最小的乙個 到達點u時,將其入棧 拓展點u後代 當且僅當dfn u low u 時,棧頂元素全部出棧,此時出...