Tarjan點的雙聯通(尋找割點)

2021-07-25 08:57:41 字數 2646 閱讀 1774

問題概述:給你乙個無向聯通圖,你要在圖中標記一些點,使得這個圖中的任意乙個點消失了,剩餘的點都可以通 過

一條路徑到達你某個標記的點。

問你最少需要選擇多少個點,並且在最優的情況下有多少總選點方案,(每個樣 例輸

入的第乙個數m表示圖中有多少條邊,當m為0時讀入結束)

輸入樣例:                                對應輸出:

9                                                case 1: 2 4

1 3   4 1

3 5   1 2

2 6   1 5

6 3   1 6   3 2

uvalive - 5135

點雙連通圖:該無向圖中的任意兩個頂點間都存在兩條點不相交的路徑

(或是說該圖中去掉任意乙個點都不會影響

其聯通性)

定理:①如果乙個連通圖不是點雙聯通圖,那麼必定存在至少乙個點,如果這個點消失,圖就會被分成多塊,這樣的點也

被稱為割點

②點雙聯通分量一定是邊雙聯通分量(除兩點一線的特殊情況),反之不一定

③點雙聯通分量可以有公共點

trajan主要原理:

time[k]:第一次遍歷到k點的時間

low[k]:k點所在點雙聯通分量子圖中第乙個被搜到的點的time值

vis[k]:k點是否已經遍歷

主要思路:一般來講無論求解點雙聯通還是邊雙連通都是邊入棧,如果點入棧,而因為性質③,你將乙個點出棧

後,還可能有別的點雙聯通分量包含它,所以點入棧會導致一些錯誤和麻煩,但這裡

有種方法可以不需要棧,大概

思路是把所有的割點找出來(割點

的time值一定會小於等於他搜尋子樹兒子點的low值,至於為什麼?很顯然如果

乙個點不是割點,

那麼它必定在一

環上或它自身是乙個點雙聯通分量,考慮前者:那麼這個點的深搜子樹一定

與他的某個父親相連線,這樣這個

點兒子的low值就會是這個點某個

父親的low值,所以一定小於本身的time 值;

考慮後者,它就不存在深搜子樹更

沒有兒子,根本不會比較),然後再搜尋一遍找出所有在同一點雙聯通分量 中的

點即可。

注意:搜尋對於根節點因為

它沒有父親節點,所以無法通過上述方法判斷根是否是割點,那怎麼辦?如

果根有兩個

搜尋子樹,那麼它一定是個

割點,反之不是

搜尋過程:

→當點k有與點c相連,如果此時(time[k]時)c沒有搜過,搜尋c點,當c點及其子樹搜尋完畢回溯後,low[k] =

min(low[k], low[c]),如果此時low[c]的值》=time[k]的值,則說明點k是割點,否則不是

→當點k有與點c相連,如果此時(time[k]時)c已經搜過,low[k] = min(low[k], time[c])

期間保證:每個點每條邊都只被搜尋1次,且必須搜尋1次,複雜度n+m,

此題題解:

看懂這題後第一眼想到是此圖有多少個點雙聯通分量,那麼就至少需要標記多少個點,然後情況數就是所有點雙聯

通分量中點個數的乘積,但沒這麼簡單,要注意以下兩點:

①:如果這個圖本身是個點雙聯通分量,那麼還是必須要標記兩個點,因為有可能標記的點會被去掉,情況數就是

n*(n-1)/2,其中n為圖中點的數量

②:如果乙個點雙聯通分量中有不止乙個割點,那麼這個點雙聯通分量中就不需要標記任何乙個點,因為其中乙個

割點被去掉,還可以走另外乙個割點到另乙個雙連通分量中

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

vectorg[50005];

setst;

int n, t, sum, cutsum, vis[50005], low[50005], time[50005], cut[50005];

void tarjan(int u, int p);

void sech(int u);

int main(void)

tarjan(1, 0);

memset(vis, 0, sizeof(vis));

st.clear();

ans = 1, bet = 0;

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

}} if(cutsum==0)

printf("case %d: 2 %lld\n", cas++, (long long)n*(n-1)/2);

else

printf("case %d: %lld %lld\n", cas++, bet, ans);

} return 0;

}void tarjan(int u, int p)

else

low[u] = min(low[u], time[v]); }}

void sech(int u)

{ int i, v;

sum++;

vis[u] = 1;

for(i=0;i

tarjan雙聯通求割點和橋模板

詳見 求割點 int n,m,stamp,low 1005 dfn 1005 iscut 1005 iscut記錄的為割點 vector vec 1005 void tarjan int index,int fa else if dfn tmp fa if fa 0 child 1 iscut in...

割點 割邊 tarjan

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

割點割頂tarjan

原題 首先tarjan求割點的重點就是dfn和low陣列的理解。dfn i 就是時間戳,即在什麼時刻搜尋到了點i,low i 則是i點能回溯到的dfn最小的祖先,搜尋的時候判斷一下當對於點x存在兒子節點y,使得dfn x low y 則x一定是割點。因為只要x的子節點不能回溯到x的上面,就是沒有返祖...