割點 割邊 tarjan

2022-03-01 12:42:34 字數 3472 閱讀 2907

洛谷割點模板題——傳送門

割邊:在連通圖中,刪除了連通圖的某條邊後,圖不再連通。這樣的邊被稱為割邊,也叫做橋。

割點:在連通圖中,刪除了連通圖的某個點以及與這個點相連的邊後,圖不再連通。這樣的點被稱為割點。

dfs搜尋樹:用dfs對圖進行遍歷時,按照遍歷次序的不同,我們可以得到一棵dfs搜尋樹。

樹邊:在搜尋樹中的藍色線所示,可理解為在dfs過程中訪問未訪問節點時所經過的邊,也稱為父子邊

回邊:在搜尋樹中的橙色線所示,可理解為在dfs過程中遇到已訪問節點時所經過的邊,也稱為返祖邊、後向邊

觀察dfs搜尋樹,我們可以發現有兩類節點可以成為割點。對根節點u,若其有兩棵或兩棵以上的子樹,則該根結點u為割點;對非葉子節點u(非根節點),若其中的某棵子樹的節點均沒有指向u的祖先節點的回邊,說明刪除u之後,根結點與該棵子樹的節點不再連通;則節點u為割點。對於根結點,顯然很好處理;但是對於非葉子節點,怎麼去判斷有沒有回邊是乙個值得深思的問題。我們用dfn[u]記錄節點u在dfs過程中被遍歷到的次序號,low[u]記錄節點u或u的子樹通過非父子邊追溯到最早的祖先節點(即dfs次序號最小),那麼low[u]的計算過程如下。

對於給的例子,其求出的dfn和low陣列如下。

id     1 2 3 4 5 6

dfn   1 2 3 4 5 6

low   1 1 1 4 4 4

可以發現,對於情況2,當(u,v)為樹邊且low[v]≥dfn[u]時,節點u才為割點。而當(u,v)為樹邊且low[v]>dfn[u]時,表示v節點只能通過該邊(u,v)與u連通,那麼(u,v)即為割邊。tarjan演算法的時間複雜度是o(n+m)的,非常快。

——附帶碼

#include #include 

#include

#include

#include

using

namespace

std;

const

int maxn = 100001

;int

n, m, cnt, rp;

int next[2 * maxn], to[2 * maxn], head[maxn], low[maxn], dfn[maxn], father[maxn];//

father為父節點

vector cut_point;

vector

< pair >cut_edge;

void add(int x, int

y)void tarjan(int

u)

else

if(v != father[u]) low[u] =min(low[u], dfn[v]);

}//根節點若有兩棵或兩棵以上的子樹則該為割點

//非根節點若所有子樹節點均沒有指向u的祖先節點的回邊則為割點

if((father[u] == 0 && child > 1) || (father[u] &&flag)) cut_point.push_back(u);

}int

main()

for(i = 1; i <= n; i++)//

圖可能不聯通(mdzz的洛谷模板題)

if(!dfn[i])

tarjan(i);

sort(cut_point.begin(), cut_point.end());

s =cut_point.size();

printf(

"%d\n

", s);

for(i = 0; i < s; i++) printf("

%d ", cut_point[i]);//

輸出割點

s =cut_edge.size();

printf(

"\n%d\n

", s);

for(i = 0; i < s; i++) printf("

%d %d\n

", cut_edge[i].first, cut_edge[i].second);//

輸出割邊

return0;

}

view code

經過培訓,發現上面的**如果有重邊就會拉閘。

下面是可以應對重邊的**

1 # include 2 # include 3 # include 4 # include 

5 # include 6 # include 7 # include 8 # include 9 # include 10 # define maxn 2333

11using

namespace

std;

1213 inline void

file()

2122 inline int

get_num()

2930

intn, m, tim, cnt;

31int

dfn[maxn], low[maxn], f[maxn], to[maxn], next[maxn], head[maxn];

32 vector cut_point;

33 vector < pair >cut_edge;

3435 inline void add(int x, int

y)36

4142 inline void dfs(int u, int

fa)43

60else low[u] =min(low[u], dfn[v]);61}

62if((!f[u] && child > 1) || (f[u] &&flag)) cut_point.push_back(u);63}

6465

intmain()

6678

for(i = 1; i <= n; i++)

79if(!dfn[i])

80 dfs(i, -1

);81

for(i = 0; i < cut_point.size(); i++) printf("

%d\n

", cut_point[i]);

82 puts(""

);83

for(i = 0; i < cut_edge.size(); i++) printf("

%d %d\n

", cut_edge[i].first, cut_edge[i].second);

84 puts(""

);85

return0;

86 }

view code

tarjan割點,割邊 模板

寫的很好的一篇部落格 根節點 如果有2 個或以上 的兒子就 是割 點根節點如果有2個或以上的兒子就是割點 根節點如果有 2個或以 上的兒子 就是割點 因為去掉根節點這兩個兒子就分離了考慮其 他情 況考慮其他情況 考慮其他情況當存 在一條邊 u v當存在一條邊u v 當存在一條邊 u v 且 lo w...

tarjan求割邊割點

內容及 來自 割邊 在連通圖中,刪除了連通圖的某條邊後,圖不再連通。這樣的邊被稱為割邊,也叫做橋。割點 在連通圖中,刪除了連通圖的某個點以及與這個點相連的邊後,圖不再連通。這樣的點被稱為割點。dfs搜尋樹 用dfs對圖進行遍歷時,按照遍歷次序的不同,我們可以得到一棵dfs搜尋樹。樹邊 在搜尋樹中的藍...

tarjan演算法求割點割邊

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