演算法 Tarjan演算法求割點

2022-01-10 21:29:54 字數 2777 閱讀 8443

在圖論中,連通圖基於連通的概念。在乙個無向圖 g 中,若從頂點i到頂點j有路徑相連(當然從j到i也一定有路徑),則稱i和j是連通的。如果 g 是有向圖,那麼連線i和j的路徑中所有的邊都必須同向。如果圖中任意兩點都是連通的,那麼圖被稱作連通圖。如果此圖是有向圖,則稱為強連通圖(注意:需要雙向都有路徑)。圖的連通性是圖的基本性質。

——摘自度娘

通俗易懂,不在解釋。

舉個例子吧:

如上圖,各個節點皆可以到達任意節點,所以該圖為連通圖。

在乙個無向圖中,如果有乙個頂點集合,刪除這個頂點集合以及這個集合中所有頂點相關聯的邊以後,圖的連通分量增多,就稱這個點集為割點集合。

如果某個割點集合只含有乙個頂點x(也即是乙個割點集合),那麼x稱為乙個割點。

——摘自度娘

了解完定義之後,不難通過定義來求出圖的割點——暴力dfs。

即是:從1到n遍歷每乙個點,每次遍歷到這個點時,只需要刪除該點,判斷刪除後是否會增加聯通量即可。

這種方法時間複雜度最壞為\(o(n×(n+m))\),只要資料大一點就會被卡爆,這裡不詳細敘述。

可以參考本人的tarjan演算法縮點部落格

依然定義:dfn(時間戳),low(該集合中最早遍歷到的點的時間戳)

觀察上圖,可以發現割點求法可以分成兩種情況討論。

若該點為根節點,若有該節點擁有兩個及以上互不相連的子樹,則刪除該點會得到這些子樹。所以該點為割點。

now == root && child >= 2

若該點不為根節點,若不存在可以在dfs中可以遇到已訪問節點的連邊時(通俗的說,就是不可以找到回去的路),則該點為割點。

now != root && low[next] >= dfn[now]

low的值可以證明發現:

low的初始值為該節點的時間戳。

即是:low[now]=dfn[now]

若當前結點now的所鏈結點next正在被訪問,則low[now]=min(low[now],dfn[next])

若當前結點now的所鏈結點next未被訪問,則

low[now]=min(low[now],low[next])

void tarjan(int now, int father, int root) 

tarjan(next, now, root);

low[now] = min(low[now], low[next]);

if(now == root && child >= 2)//處理情況一

cut[now] = true;

else if(now != root && low[next] >= dfn[now])//處理情況二

cut[now] = true;

} if(next != father)

low[now] = min(low[now], dfn[next]);//更新low值 }}

void build()

附上一道板題

割點給出乙個\(n\)個點,\(m\)條邊的無向圖,求圖的割點。

第一行輸入兩個正整數\(n,m\)。

下面\(m\)行每行輸入兩個正整數\(x,y\)表示\(x\)到\(y\)有一條邊。

第一行輸出割點個數。

第二行按照節點編號從小到大輸出節點,用空格隔開。

輸入

6 7

1 21 3

1 42 5

3 54 5

5 6

輸出
1 

5

思路

板題,套上即可。

#include #include using namespace std;

const int maxn = 2e4 + 5;

vectorv[maxn];

int dfn[maxn], low[maxn];

bool cut[maxn];

int tim, cnt;

int n, m;

void read();

void build();

void tarjan(int, int, int);

int main()

void build()

void tarjan(int now, int father, int root)

tarjan(next, now, root);

low[now] = min(low[now], low[next]);

if(now == root && child >= 2)

cut[now] = true;

else if(now != root && low[next] >= dfn[now])

cut[now] = true;

} if(next != father)

low[now] = min(low[now], dfn[next]); }}

void read()

}

tarjan演算法求割點割邊

在上一節我們已經知道tarjan演算法可以求聯通圖,在這裡我們也運用tarjan的思想求割點與割邊,首先我們先來說說割點,那麼什麼事割點呢,先來看一張圖 a 來自網路 在 a 圖中,我們將a點以及與a點相連的邊全部去除,會發現這個聯通圖被分成了倆個聯通圖,乙個是節點f,另外乙個是餘下的所有的節點組成...

求割點模板(tarjan演算法思路)

想看更多模板,貼上求割點模板 const int n 110 struct data tu n n int head n low n dfn n dfn記錄某個點被訪問到的次數,low記錄某個點或其子樹回邊的最小步數的點 bool cut n 表示該點是否為割點 int ip int step,rt...

Tarjan演算法求橋和割點

預備定義 low u 定義為u或者u的子樹中能夠通過 非父子邊 追溯到的最早的節點的dfs開始時間 d u 表示dfs過程中u的進棧時間 割點 無向連通圖中,如果刪除某點後,圖變成不連通,則稱該點為割點。橋 無向連通圖中,如果刪除某邊後,圖變成不連通,則稱該邊為橋。判斷割點方法 1 u為樹根,且u有...