c++初級(jí)并查集知識(shí)點(diǎn)總結(jié)
并查集是一種樹型的數(shù)據(jù)結(jié)構(gòu),用于處理一些不交集的合并及查詢問題。
有一個(gè)聯(lián)合- 查找算法定義了兩個(gè)用于此數(shù)據(jù)結(jié)構(gòu)的操作:
- Find :確定元素屬于哪一個(gè)子集。它可以被用來確定兩個(gè)元素是否屬于同一子集。
- Union:將兩個(gè)子集合并成同一個(gè)集合。
并查集主要運(yùn)用在合并元素以及查詢兩個(gè)元素是否在同一集合的問題,在信息學(xué)競(jìng)賽中廣泛涉及
初始化:
一開始,每一個(gè)元素都是一個(gè)集合,打個(gè)比方,每個(gè)人所在的 " 家族 " 只有他一個(gè)人。我們還需要一個(gè) f 數(shù)組,里面存的是他的 “父親” 的編號(hào),初始值為 f[1]=1,f[2]=2……f[n]=n,如圖
2、find函數(shù):find(a)是用來查找a的“祖先”的,例如,我們要查找 a 的祖先,就要去找 a 的父親的父親……,直到有個(gè)人 b ,他的父親就是他自己,那么 b 就是 a 的祖先代碼如下:int find (int x){ if(f[x] == x) return x;//如果x的父親就是他自己,則x為a的祖先 else return find (f[x]);//否則a的祖先 就是a的父親的祖先}int x=find(a);find函數(shù):find(a)是用來查找a的“祖先”的,例如,我們要查找 a 的祖先,就要去找 a 的父親的父親……,直到有個(gè)人 b ,他的父親就是他自己,那么 b 就是 a 的祖先代碼如下:int find (int x){ if(f[x] == x) return x;//如果x的父親就是他自己,則x為a的祖先 else return find (f[x]);//否則a的祖先 就是a的父親的祖先}int x=find(a);
union函數(shù):
union(a,b) 就是合并 a,b 這兩個(gè)人所在的家族,只需要把 a的祖先的父親 指向 b的祖先
如何合并?我們?cè)O(shè) u=find(a),v=find(b) , 只要將 u,v 其中一個(gè)人的父親編號(hào)指向另外一個(gè)人就行了,例如 f[u]=v
代碼如下:
void Union (int a,int b)//因?yàn)閡nion是c++的保留字,所以只好大寫u { int u= find(a), v= find(b);//尋找a,b的祖先 f[u]=v;//合并家族 } Union (a,b);
在合并的時(shí)候還有一個(gè)注意點(diǎn):為什么不能直接把 a 的父親指向 b ?因?yàn)檫@樣并不能合并完全,a 的父親, a 的父親的父親……,都不能合并到 b 的家族里(想一想,為什么?),如圖
5、查詢兩個(gè)元素是否在同一集合里:查詢 a,b 是否在同一集合里,就是看他們的祖先是否相等,若相等則在同一集合里,否則就不在代碼如下:if( find(a) == find(b) ) cout<<"Y\n"; //如果祖先相等就輸出“Y”else cout<<"N\n"; //否則輸出“N”查詢兩個(gè)元素是否在同一集合里:查詢 a,b 是否在同一集合里,就是看他們的祖先是否相等,若相等則在同一集合里,否則就不在代碼如下:if( find(a) == find(b) ) cout<<"Y\n"; //如果祖先相等就輸出“Y”else cout<<"N\n"; //否則輸出“N”
例題:
至此,你應(yīng)該對(duì)并查集有了初步的了解,是時(shí)候上例題了
題目描述
如題,現(xiàn)在有一個(gè)并查集,你需要完成合并和查詢操作。
輸入輸出格式
輸入格式:
第一行包含兩個(gè)整數(shù)N、M,表示共有N個(gè)元素和M個(gè)操作。
接下來M行,每行包含三個(gè)整數(shù)Zi、Xi、Yi
當(dāng)Zi=1時(shí),將Xi與Yi所在的集合合并
當(dāng)Zi=2時(shí),輸出Xi與Yi是否在同一集合內(nèi),是的話輸出Y;否則話輸出N
輸出格式:
如上,對(duì)于每一個(gè)Zi=2的操作,都有一行輸出,每行包含一個(gè)大寫字母,為Y或者N
其實(shí),這道題目就是把上面幾個(gè)步驟綜合在一起,代碼如下
并查集的路徑壓縮
路徑壓縮,顧名思義,就是將本來要很多步完成的事情壓縮成一步
因?yàn)槲覀兠看?nbsp;find(a) 都要消耗 O (a 的層數(shù) ) 的時(shí)間,如果數(shù)據(jù)構(gòu)造成一條鏈,則每次 find 都需要 O(n) 的時(shí)間,這是我們不希望看到的
所以,我們可以把 f 數(shù)組的性質(zhì)改變一下 f[a] 指向的編號(hào)變?yōu)?nbsp;a 的祖先
代碼該怎么寫呢?我們只需要在 find 函數(shù)里把
return find (f[x]);
變成
return f[x]=find(f[x]);
就可以了
這樣每一次 find 都會(huì)使路徑上的每個(gè) f[x] 指向 x 的祖先,每一次 find 也就只需要 1 步就行了(除非被合并過,那也只需要 2 步),這就是路徑壓縮的實(shí)質(zhì)
欄 目:C語言
下一篇:OpenCV實(shí)現(xiàn)鼠標(biāo)在圖像上框選單目標(biāo)和多目標(biāo)
本文標(biāo)題:c++初級(jí)并查集知識(shí)點(diǎn)總結(jié)
本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/236.html
您可能感興趣的文章
- 04-02c語言沒有round函數(shù) round c語言
- 01-10如何判斷一個(gè)數(shù)是否為2的冪次方?若是,并判斷出來是多少次方
- 01-10深入理解C++中常見的關(guān)鍵字含義
- 01-10使用C++實(shí)現(xiàn)全排列算法的方法詳解
- 01-10如何判斷一個(gè)數(shù)是否為4的冪次方?若是,并判斷出來是多少次方
- 01-10c++中inline的用法分析
- 01-10用C++實(shí)現(xiàn)DBSCAN聚類算法
- 01-10全排列算法的非遞歸實(shí)現(xiàn)與遞歸實(shí)現(xiàn)的方法(C++)
- 01-10C++大數(shù)模板(推薦)
- 01-10淺談C/C++中的static與extern關(guān)鍵字的使用詳解


閱讀排行
- 1C語言 while語句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹的示例代碼(圣誕
- 3利用C語言實(shí)現(xiàn)“百馬百擔(dān)”問題方法
- 4C語言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言的正則匹配函數(shù) c語言正則表達(dá)
- 04-02c語言用函數(shù)寫分段 用c語言表示分段
- 04-02c語言中對(duì)數(shù)函數(shù)的表達(dá)式 c語言中對(duì)
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段
- 04-02C語言中怎么打出三角函數(shù) c語言中怎
- 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求
隨機(jī)閱讀
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 01-10delphi制作wav文件的方法
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 01-10使用C語言求解撲克牌的順子及n個(gè)骰子
- 01-11ajax實(shí)現(xiàn)頁面的局部加載
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 01-10C#中split用法實(shí)例總結(jié)
- 04-02jquery與jsp,用jquery