爆炒洋蔥圈 HDU 1213 並查集初學

2021-09-11 16:35:50 字數 2578 閱讀 4310

雖說做專案會讓人有成就感,但是演算法這種考驗基礎的東西不能落下。更何況我演算法那麼差呢。最近在刷學校的oj準備ccf,刷到了並查集,寫下這篇文章供自己以後和後來人查閱。如有紕漏,敬請指教。

並查集是一種樹形的資料結構,用於處理一些不相交集合的合併和查詢問題。常常在使用中以森林來表示

description

今天是ignatius的生日,他邀請了許多朋友。現在是吃晚飯的時間,ignatius想知道他至少需要準備多少桌。必須注意的是,並非所有的朋友都相互認識對方,有的人不願意和陌生人坐在一桌。針對此問題的乙個重要的規則是,如果我告訴你a知道b,b知道c,這意味著,a和c認識對方,這樣他們就可以留在乙個桌子。但是如果我告訴你,a知道b,b知道c,d知道e,那麼abc可以坐在一起,de就得另外再坐一桌了。你的任務是請根據輸入的朋友之間的關係,幫助ignatius 求出需要安排多少桌。

input

輸入第一行是乙個數字t(1≤t≤25),表示一共有多少組資料。隨後跟有t組資料,每一組資料的第一行是兩個數字n和m(1≤n,0≤m≤1000)。n代表有多少個朋友,並且朋友從1到n編號。然後有m行輸入,每一行輸入包含兩個int a和b(a!=b),代表a和b互相認識。兩組資料之間有一行空行。

output

對於每一組資料,只需要輸出ignatius至少需要準備多少張台。不要輸出任何空格。

樣例見oj

初步分析問題實質上是乙個圖論中判斷兩個點是否存在連通子圖的問題。但用圖的資料結構的最大問題就是,我們無法存下多至(m=)2 000 000條邊的圖,後面關於演算法時效等諸多問題就免談了。

用圖表示關係過於「奢侈」了。其實本題只是乙個對分離集合(並查集)操作的問題。

在c++中,具體的實現思路是這樣的:

具體給出乙個例項

對於上面的這些步驟,我們需要幾個資料結構和函式來處理(先不考慮路徑壓縮)。

先貼出自己寫的**,在**中會有詳盡的注釋

#include

#include

#include

using

namespace std;

//並查集

//我寫的這段**有問題 三次更改後ac

//不能直接壓縮路徑

//查詢函式

intfind

(int pre,

int&node)

return

find

(pre, pre[node]);

}//聯合函式

void

join

(int pre,

int first,

int second)

}int

main()

for(

int j =

0; j < totalrelationships; j++

)int totaldesk =0;

for(

int j =

1; j <= totalfriends; j++)}

result[i]

= totaldesk;

}for

(int i =

0; i < totalcases; i++

)system

("pause");

}

在本題當中,由於不需要查詢兩個節點之間的關係,只需要輸出至少要準備多少張台(有多少個非聯通集合,進一步講就是有多少個根節點),所以對產生的樹進行路徑壓縮是不必要的。

但是考慮下面這種情況,如果要查詢兩個人是否能夠坐在同一張桌子,那麼就要對代表這兩個朋友的節點進行查詢,如果存在於同乙個集合那麼他們可以坐在一起,否則就不能。

而由於我們不知道通過上面的**構造的樹是什麼樣子的,有可能是正常的樹,也有可能構造的樹比較極端導致樹退化成煉表,那麼查詢帶來的時間開銷將會非常大。那麼我們就需要對構造的樹進行路徑壓縮處理。

示意圖如下

上面說過,如果想要知道有多少個非聯通集合,那麼只需要查詢有多少個根節點就可以了。而如果想要判斷兩個節點是否在同一集合內,只要判斷他們兩個的根節點是否相同即可。那麼我們就可以對我們構造的數進行優化,將樹的高度減少為2,每個子節點都直接和根節點聯通。這樣查詢的時間消耗將會被大大減少。

給出路徑壓縮函式

//路徑壓縮函式

void

zip(

int pre,

int totalfriends)

}

上面的知識只能夠簡單用於判斷有多少個非聯通集合或者兩個節點是否處於乙個集合內,而對於比較複雜的問題可能需要帶權並查集來解決。希望自己將來能夠學到相關的知識。

並查集/9388442?fr=aladdin

陳思聰2023年3月1日 12:08:24

hdu1213並查集模板

題意 n個人吃飯 給出認識的關係,認識的才能在一張桌子上吃飯,求最少需要幾張桌子 思路 沒給出兩人關係,放入 並查集中 最後查詢父節點的數目即可 include include include include include include using namespace std int n,m i...

hdu1213 並查集板子

並查集是一種支援合併與查詢的資料結構,在森林中進行操作,加上路徑壓縮,合併和查詢的時間複雜度幾乎都是常數。並查集最基礎的作用就是建立不同的點之間的所謂的 關係 並且查詢兩者是否有關係。並查集的乙個特點是向量型關係傳遞性,比如a b b c,則有a c,是不是特別像向量之間的傳遞?在很多時候並查集的應...

HDU 1213有意思的並查集 掌門

深夜未耕 乙個典型的並查集 參考 借用了裡面的掌門學說注釋這道題 include using namespace std int pre 1010 你不知道吧 我乙個人在寢室 放著楊千嬅的小星星 對面你發來一句話 我對著螢幕空空地說 我喜歡你 我喜歡你你聽到了嗎 聽不到也沒關係 我在慢慢像你靠近 i...