概念
1.橋:是存在於無向圖中的這樣的一條邊,如果去掉這一條邊,那麼整張無向圖會分為兩部分,這樣的一條邊稱為橋無向連通圖中,如果刪除某邊後,圖變成不連通,則稱該邊為橋。
2.割點:無向連通圖中,如果刪除某點後,圖變成不連通,則稱該點為割點。
割點特點:1)當前節點為樹根的時候,條件是「要有多餘一棵子樹」(如果這有一顆子樹,去掉這個點也沒有影響,如果有兩顆子樹,去掉這點,兩顆子樹就不連通了。)
2)當前節點u不是樹根的時候,條件是「low[v]>=dfn[u]」,也就是在u之後遍歷的點,能夠向上翻,最多到u,(如果能翻到u的上方,那就有環了,去掉u之後,圖仍然連通。)
橋的特點:若是一條無向邊(u,v)是橋,
1)當且僅當無向邊(u,v)是樹枝邊的時候,需要滿足dfn(u)注意點:
1)求橋的時候:因為邊是無方向的,所以父親孩子節點的關係需要自己規定一下,
在tarjan的過程中if(v不是u的父節點) low[u]=min(low[u],dfn[v]);
因為如果v是u的父親,那麼這條無向邊就被誤認為是環了。
2)找橋的時候:注意看看有沒有重邊,有重邊的邊一定不是橋,也要避免誤判。
也可以先進行tarjan(),求出每乙個點的dfn和low,並記錄dfs過程中的每個點的父節點,遍歷所有點的low,dfn來尋找橋和割點
(dfn[u]表示u點第一次訪問到的時間戳,low[u],表示以及u的子孫所能到達的最小時間戳)
#includeusingnamespace
std;
#include
#include
#include
#define n 201vector
g[n];
intn,m,low[n],dfn[n];
bool
is_cut[n];
intfather[n];
int tim=0
;void tarjan(int i,int
father)
else
if(father!=k)/*
假如k是i的父親的話,那麼這就是無向邊中的重邊,有重邊那麼一定不是橋
*/low[i]=min(low[i],dfn[k]);//
dfn[k]可能!=low[k],所以不能用low[k]代替dfn[k],否則會上翻過頭了。}}
intmain()
memset(dfn,-1,sizeof
(dfn));
memset(father,
0,sizeof
(father));
memset(low,-1,sizeof
(low));
memset(is_cut,
false,sizeof
(is_cut));
int rootson=0
; tarjan(
1,0);
for(int i=2;i<=n;++i)
return0;
}
tarjan求割點和橋(割邊)
tarjan求割點和橋 例題 割點 重要的地方在 中都有注釋 include define ll long long using namespace std const ll m 2e4 10,maxn 3e6 30 int dfn m low m tot int e m 1 k,p m k2 ve...
Tarjan演算法求橋和割點
預備定義 low u 定義為u或者u的子樹中能夠通過 非父子邊 追溯到的最早的節點的dfs開始時間 d u 表示dfs過程中u的進棧時間 割點 無向連通圖中,如果刪除某點後,圖變成不連通,則稱該點為割點。橋 無向連通圖中,如果刪除某邊後,圖變成不連通,則稱該邊為橋。判斷割點方法 1 u為樹根,且u有...
tarjan求橋 割頂
若low v dfn u 則 u,v 為割邊。但是實際處理時我們並不這樣判斷,因為有的圖上可能有重邊,這樣不好處理。我們記錄每條邊的標號 一條無向邊拆成的兩條有向邊標號相同 記錄每個點的父親到它的邊的標號,如果邊 u,v 是v的父親邊,就不能用dfn u 更新low v 這樣如果遍歷完v的所有子節點...