同步
原題鏈結
簡要題意:
給定乙個圖,求所有割點。
割點(割頂)的定義:去掉該點整個圖不連通。
前置知識:
強連通分量的 tarjan
\texttt
tarjan
求法。不懂的可以先去了解下
本題作為 tarjan
\texttt
tarjan
求割點的模板題。
首先,我們同樣和求強連通分量一樣,搞出乙個 dfn
\text
dfn 和 low
\text
low.
接著,你會發現這樣的情況:
如果 x
xx 節點後面搜尋樹上的點 y
yy 都滿足 low
y≥
xlow_y \geq x
lowy≥
x,此時 x
xx不出意外是乙個割點。
那 「意外」 指什麼?
想一下,如果是一條鏈的鏈頂,同樣也滿足 low
y≥x(
y∈
subtree(x)
)low_y \geq x(y \in \texttt)
lowy≥
x(y∈
subtree(x)
),但它不是割點。
因此,我們從 p
pp 節點開始搜尋,就要判斷清楚,p
pp 到底是不是?
應該是這樣的:如果 p
pp 有超過 1
11 個兒子,說明把它弄掉之後那 >
1>1
>
1 個兒子走不通,所以 p
pp 是割點。
否則 ≤
1\leq 1
≤1個兒子顯然不是割點,這是要特殊判斷的。
答案如何記錄?你注意到需要將答案去重,排序(因為乙個點可能被它的每乙個子樹重複的記錄多次)。那麼顯然就是用 set
\texttt
set 解決!
智商不夠,資料結構來湊
set\texttt
set 的到來憑空給時間增加乙個 log
\texttt
log,但是沒有關係,因為本來 tarjan
\texttt
tarjan
就是線性的。
(其實明明可以先雜湊的,可是用 stl
\text
stl 多快樂啊·)
注意細節即可通過。
時間複雜度:o(n
logn+
m)
o(n \log n + m)
o(nlogn+
m).實際得分:100pt
s100pts
100pts
.
#pragma gcc optimize(2)
#include
using
namespace std;
const
int n=
1e5+1;
inline
intread()
int x=0;
while
(ch>=
'0'&& ch<=
'9') x=
(x<<3)
+(x<<1)
+ch-
'0',ch=
getchar()
;return x*f;
}int low[n]
,dfn[n]
,fa[n]
,n,m,cnt=0;
bool vis[n]
; set<
int>s;
vector<
int>g[n]
;inline
void
tarjan
(int u)
else
if(v!=fa[u]
) low[u]
=min
(low[u]
,dfn[v]);
//同樣記錄}if
(fa[u]
==u && sum>=
2) s.
insert
(u);
//最後判斷起始點
}int
main()
for(
int i=
1;i<=n;i++)if
(!vis[i]
) cout
int>
::iterator i=s.
begin()
;i!=s.
end(
);i++
)printf
("%d "
,*i)
;//記得是空格隔開,不是答案換行
return0;
}
P3388 模板 割點(割頂)
割點 題目描述 給出乙個n個點,m條邊的無向圖,求圖的割點。輸入格式 第一行輸入n,m 下面m行每行輸入x,y表示x到y有一條邊 輸出格式 第一行輸出割點個數 第二行按照節點編號從小到大輸出節點,用空格隔開 輸入樣例 1 複製6 7 1 21 3 1 42 5 3 54 5 5 6輸出樣例 1 複製...
P3388 模板 割點(割頂)
割點 給出乙個n個點,m條邊的無向圖,求圖的割點。輸入格式 第一行輸入n,m 下面m行每行輸入x,y表示x到y有一條邊 輸出格式 第一行輸出割點個數 第二行按照節點編號從小到大輸出節點,用空格隔開 輸入樣例 1 6 7 1 21 3 1 42 5 3 54 5 5 6 輸出樣例 1 1 5 n,m均...
P3388 模板 割點(割頂)
n 給定一張無向圖g g g,求圖的割點 s ol utio nsolution soluti on判斷條件 非搜尋樹起點x xx,任意乙個子節點y yy,滿足dfn x l ow y dfn x low y dfn x l ow y 搜尋樹起點rtrt rt,至少兩個子節點y yy,滿足dfn x...