並查集 生成樹回顧專題

2021-09-27 22:03:52 字數 3073 閱讀 7241

poj1679

問並查集是否唯一

題解:考慮kruscal,從小到大將邊相同的分為一組。然後對於每一組單獨考慮,篩掉與之前組衝突的邊(先不合併)。然後將剩下的邊用個並查集判斷一下即可。

poj2912

題意:n個人剪刀石頭布,每個人只能出一種。但是有乙個裁判可以隨意出。給出比賽資訊,問n個人中是否有裁判,以及裁判在至少第幾個可以確定?

列舉裁判,然後忽略掉裁判,剩下的用乙個並查集來判斷是否合法。具體的判斷過程是,如果兩個人的勝負關係確定,那麼他們所在的並查集的根的勝負關係也確定。然後我們可以用相對距離來衡量勝負關係。然後合併的時候,先維護出fa和兩個端點分別到根的相對路徑。推到出根的相對路徑。然後再合併根。查詢也同理。然後根據是否能滿足多個裁判,已經所有人在作為裁判時,至少在第幾個比賽結果發生衝突來得出答案。

poj2728

問乙個 ∑co

st/l

en

\sum

∑cost/

len最小的生成樹

01分數規劃,沒什麼好說。但是這題是稠密圖,然後卡了kruscal。只能寫prim。prim大概思想就是在確定了的點和未確定的點之間找最短邊來生成樹即可,然後每次用確定了的新點來更新新的最短邊。注意分數規劃方向別搞反了。

poj1639

對於乙個確定的根節點有k度數限制的最小生成樹

演算法如下:

1.先不考慮根節點,做最小生成樹,得到m個連通塊。若m>k則這樣的生成樹不存在。然後從根節點連向m個連通塊連最短路徑得到度數為m的生成樹。

2.從根節點跑個dp,dp[i]表示從根節點到i所經過路徑的最大值。若直接相連則為-inf

3.找出乙個edge[1][i]-dp[i]最小的邊,連上該邊,刪除dp[i]的邊。該邊必須小於0,否則演算法結束。重複2-3找到答案

poj3164

最小樹形圖板子題(有向圖的最小生成樹)

演算法如下:

1)求最短弧集合 e

2)判斷集合 e 中有沒有有向環,如果有轉步驟 3,否則轉 4

3)收縮點,把有向環收縮成乙個點,並且對圖重新構建,包括邊權值的改變和點的處理,之後再轉步驟 1

4)展開收縮點,求得最小樹形圖

具體看板子,如果要求最小樹形圖的方案的話。不能直接考慮,因為若當前邊刪除了,以後可能會加回來。這樣我們就記錄刪除的方案,然後從後往前時間回溯獲得最後邊的存在狀況即可

若無規定起點的最小樹形圖則選乙個超級源點,對1~n都連邊為inf。然後途中如果有起點為超級源點的邊被選入最短路集合的話,那麼終點即是樹形圖的起點

牛客多校第8場e

有(1<=n<=1e5)個點,(1<=m<=1e5)條邊,每條邊有兩個權值l,r。表示只有編號為l~編號為r的人才能通過這條邊。問有多少人可以從1走到n

#include

#define pii pair

#define fi first

#define se second

#define lc o*2

#define rc o*2+1

#define ll long long

using

namespace std;

const

int maxn =

400005

;int n,m;

int a[maxn]

,b[maxn]

,l[maxn]

,r[maxn]

;vectorv[

4*maxn]

;int fa[maxn]

,sz[maxn]

;//按秩合併的並查集,不壓縮路徑

ll ans =0;

intfind

(int x)

int c[maxn]

,cnt;

void

update

(int o,

int l,

int r,

int ql,

int qr,

int id));

return;}

int m =

(l+r)

>>1;

if(ql<=m)

update

(lc,l,m,ql,qr,id);if

(qr>m)

update

(rc,m+

1,r,ql,qr,id);}

void

query

(int o,

int l,

int r)

fa[fy]

=fx;

cc.push_back()

;//記錄之前的樣子

tmp.

push_back

(fy)

; sz[fx]

+=sz[fy];}

if(find(1

)==find

(n))

int m =

(l+r)

>>1;

if(!flag&&lfor(

auto t:tmp)

for(

auto t:cc)

//樣子變回去

}int

main()

sort

(c+1

,c+1

+cnt)

; cnt=

unique

(c+1

,c+1

+cnt)

-(c+1)

;for

(int i=

1; i<=m; i++

)query(1

,1,cnt)

; cout

}/*5 51 2 1 5

2 3 1 3

3 5 3 5

2 4 1 3

4 5 3 5

*/

並查集 最小生成樹專題

並查集 樸素並查集和帶權並查集 並查集介紹 難點 路徑壓縮和啟發式合併的理解 常用模板 1 樸素並查集 int p n 儲存每個點的祖宗節點 返回x的祖宗節點 intfind int x 初始化,假定節點編號是1 n for int i 1 i n i p i i 合併a和b所在的兩個集合 p fi...

並查集專題

洛谷p3144 usaco16open 關閉農場關閉農場 離線的反著的並查集 看看在不在乙個集合內 include include include include using namespace std int n,m int f 99999 a 3009 3099 b 3999 int ans 1...

並查集演算法回顧

並查集就是有關集合的合併和查詢演算法 對於每個集合來說我們都有乙個標誌 這個集合中的所有元素都指向這個標誌 我們可以定義a的標誌為set a 我們就可以利用這些標誌來進行集合的合併和查詢 在最開始的時候要memset set,1,sizeof set 至於為什麼後面可以自己體會 現在介紹兩個函式 i...