并查集(還有反集也在)

?一.定義


定義:
并查集是一種樹型的數據結構,用于處理一些不相交集合的合并及查詢問題(即所謂的并、查)。比如說,我們可以用并查集來判斷一個森林中有幾棵樹、某個節點是否屬于某棵樹等。

主要構成:
并查集主要由一個整型數組pre[ ]和兩個函數find( )、join( )構成。
數組 pre[ ] 記錄了每個點的前驅節點是誰,函數 find(x) 用于查找指定節點 x 屬于哪個集合,函數 join(x,y) 用于合并兩個節點 x 和 y 。

作用:
并查集的主要作用是求連通分支數(如果一個圖中所有點都存在可達關系(直接或間接相連),則此圖的連通分支數為1;如果此圖有兩大子圖各自全部可達,則此圖的連通分支數為2……)

?二.代碼

find( )函數的定義與實現

故事引入:
子夜,小昭于驪山下快馬送信,發現一頭戴竹笠之人立于前方,其形似黑蝠,倒掛于樹前,甚懼,正系拔劍之時,只聽四周悠悠傳來:“如此夜深,姑涼竟敢擅闖明教,何不下坐陪我喝上一盅?”。小昭聽聞,后覺此人乃明教四大護法之一的青翼蝠王韋一笑,答道:“在下小昭,乃紫衫龍王之女”。蝠王輕惕,急問道:“爾等既為龍王之女,故同為明教中人。敢問閣下教主大名,若非本教中人,于明教之地肆意走動那可是死罪!”。小昭嚇得趕緊打了個電話問龍王:“龍王啊,咱教主叫啥名字來著?”,龍王答道:“吾教主乃張無忌也!”,小昭遂答蝠王:“張無忌!”。蝠王聽后,抱拳請禮以讓之。
在上面的情境中,小昭向他的上級(紫衫龍王)請示教主名稱,龍王在得到申請后也向他的上級(張無忌)請示教主名稱,此時由于張無忌就是教主,因此他直接反饋給龍王教主名稱是“張無忌”。同理,青翼蝠王也經歷了這一請示過程。
在并查集中,用于查詢各自的教主名字的函數就是我們的find()函數。find(x)的作用是用于查找某個人所在門派的教主,換言之就是用于對某個給定的點x,返回其所屬集合的代表。

實現:
首先我們需要定義一個數組:int pre[1000]; (數組長度依題意而定)。這個數組記錄了每個人的上級是誰。這些人從0或1開始編號(依題意而定)。比如說pre[16]=6就表示16號的上級是6號。如果一個人的上級就是他自己,那說明他就是教主了,查找到此結束。也有孤家寡人自成一派的,比如歐陽鋒,那么他的上級就是他自己。
每個人都只認自己的上級。比如小昭只知道自己的上級是紫衫龍王。教主是誰?不認識!要想知道自己教主的名稱,只能一級級查上去。因此你可以視find(x)這個函數就是找教主用的。
下面給出這個函數的具體實現:

int find(int x)					//查找x的教主
{while(pre[x] != x)			//如果x的上級不是自己(則說明找到的人不是教主)x = pre[x];				//x繼續找他的上級,直到找到教主為止return x;					//教主駕到~~~
}

?

join( )函數的定義與實現


故事引入:
虛竹和周芷若是我個人非常喜歡的兩個人物,他們的教主分別是玄慈方丈和滅絕師太,但是顯然這兩個人屬于不同門派,但是我又不想看到他們打架。于是,我就去問了下玄慈和滅絕:“你看你們倆都沒頭發,要不就做朋友吧”。他們倆看在我的面子上同意了,這一同意非同小可,它直接換來了少林和峨眉的永世和平。

實現:
在上面的情景中,兩個已存的不同門派就這樣完成了合并。這么重大的變化,要如何實現?要改動多少地方?其實很簡單,我對玄慈方丈說:“大師,麻煩你把你的上級改為滅絕師太吧。這樣一來,兩派原先所有人員的教主就都變成了師太,于是下面的人們也就不會打起來了!反正我們關心的只是連通性,門派內部的結構不要緊的”。玄慈聽后立刻就不樂意了:“我靠,憑什么是我變成她手下呀,怎么不反過來?我抗議!”。抗議無效,我安排的,最大。反正誰加入誰效果是一樣的,我就隨手指定了一個,join()函數的作用就是用來實現這個的。

join(x,y)的執行邏輯如下:
1、尋找 x 的代表元(即教主);
2、尋找 y 的代表元(即教主);
3、如果 x 和 y 不相等,則隨便選一個人作為另一個人的上級,如此一來就完成了 x 和 y 的合并。
下面給出這個函數的具體實現:

void join(int x,int y)                     //我想讓虛竹和周芷若做朋友
{int fx=find(x), fy=find(y);            //虛竹的老大是玄慈,芷若MM的老大是滅絕if(fx != fy)                           //玄慈和滅絕顯然不是同一個人pre[fx]=fy;                        //方丈只好委委屈屈地當了師太的手下啦
}

總結


1、用集合中的某個元素來代表這個集合,則該元素稱為此集合的代表元;
2 、一個集合內的所有元素組織成以代表元為根的樹形結構;
3 、對于每一個元素 x,pre[x] 存放 x 在樹形結構中的父親節點(如果 x 是根節點,則令pre[x] = x);
4 、對于查找操作,假設需要確定 x 所在的的集合,也就是確定集合的代表元。可以沿著pre[x]不斷在樹形結構中向上移動,直到到達根節點。
因此,基于這樣的特性,并查集的主要用途有以下兩點:
1、維護無向圖的連通性(判斷兩個點是否在同一連通塊內,或增加一條邊后是否會產生環);
2、用在求解最小生成樹的Kruskal算法里。


一般來說,一個并查集對應三個操作:
1、初始化( Init()函數 )
2、查找函數( Find()函數 )
3、合并集合函數( Join()函數 )

#include<bits/stdc++.h>
using  namespace std;
#define int long long
int n,m;
int pre[10007];
void init(){for(int i=1;i<=n;i++){pre[i]=i;//每個結點的上級都是自己 }
}
int find(int x){ //查找結點 x的根結點 if(pre[x]!=x){pre[x]=find(pre[x]);//遞歸出口:x的上級為 x本身,則 x為根結點 }return pre[x];//遞歸查找 
}
void join(int x,int y){int fx=find(x);//尋找 x的代表元int fy=find(y);//尋找 y的代表元if(fx!=fy){//不同集合則合并pre[fx]=fy;}
}
bool isSame(int x,int y){return find(x)==find(y);
}
signed main(){ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin>>n>>m;init();while(m--){int num;cin>>num;if(num==1){int x,y;cin>>x>>y;join(x,y);}else{int x,y;cin>>x>>y;if(isSame(x,y)==0){cout<<"N"<<endl;}else{cout<<"Y"<<endl;}}}system("pause");return 0;
}

三.例題一?

?

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,m,k;
int pre[10010];
void init(){for(int i=1;i<=n;i++){pre[i]=i;}
}
int find(int x){if(pre[x]!=x){pre[x]=find(pre[x]);}return pre[x];
}
void join(int x,int y){int fx=find(x);int fy=find(y);if(fx!=fy){pre[fx]=fy;}
}
bool issame(int x,int y){return find(x)==find(y);
}
int main(){cin>>n>>m>>k;init();while(m--){int a,b;cin>>a>>b;join(a,b);}while(k--){int a,b;cin>>a>>b;if(issame(a,b)){cout<<"Yes"<<endl;}else{cout<<"No"<<endl;}}system("pause");return 0;
}

??

四.例題二 (加反集)

?

?

關于反集

我也是做這道題才知道的

如果a和b是敵人,合并n+b和a,n+a和b

如果c和a是敵人,合并n+c和a,n+a和c

那么b和c就并在一起了

這樣就符合了題目敵人的敵人是朋友的規則

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,k;
int pre[10010];
map<int,int> mp;
void init(){for(int i=1;i<=2*n;i++){pre[i]=i;//這里初始化為2*n}
}
int find(int x){if(pre[x]!=x){pre[x]=find(pre[x]);}return pre[x];
}
void join(int x,int y){int fx=find(x);int fy=find(y);if(fx!=fy){pre[fx]=fy;}
}
int main(){cin>>n>>k;init();while(k--){string s;cin>>s;int a,b;cin>>a>>b;if(s=="F"){join(a,b);}else if(s=="E"){join(n+a,b);join(n+b,a);}}int cnt=0;for(int i=1;i<=n;i++){if(pre[i]==i) cnt++;}cout<<cnt<<endl;system("pause");return 0;
}

?

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/42622.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/42622.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/42622.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

PHP-實例-文件上傳

1 需求 2 basename 在 PHP 中&#xff0c;basename() 函數用于返回路徑中的文件名部分。如果路徑中包含了文件擴展名&#xff0c;則該函數也會返回它。如果路徑的結尾有斜杠&#xff08;/&#xff09;或反斜杠&#xff08;\&#xff09;&#xff0c;則 basename() 函數會返回空…

Android計算器界面的設計——表格布局TableLayout實操

目錄 任務目標任務分析任務實施 任務目標 使用TextView、Button等實現一個計算器界面&#xff0c;界面如圖1所示。 圖1 計算器界面效果圖 任務分析 界面整體使用表格布局&#xff0c;第一行使用一個TextView控件&#xff0c;橫跨4列&#xff0c;中間4行4列&#xff0c;最后一…

Laravel HTTP客戶端:網絡請求的瑞士軍刀

標題&#xff1a;Laravel HTTP客戶端&#xff1a;網絡請求的瑞士軍刀 Laravel的HTTP客戶端是一個功能強大的工具&#xff0c;它提供了一種簡潔、直觀的方式來發送HTTP請求。無論是與外部API集成&#xff0c;還是進行網絡數據抓取&#xff0c;Laravel的HTTP客戶端都能滿足你的需…

小紅書選品中心商家采集 小紅書商家電話采集軟件

可采集名稱銷量評分聯系方式等 需要有1000粉絲以上已實名認證過的小紅書達人才可以使用 以下是一個示例程序&#xff0c;可以用于批量獲取小紅書選品中心商家的信息&#xff1a; import requestsdef get_merchants(page_num):url f"https://www.xiaohongshu.com/selec…

git 添加本地分支, clean

//以develop為源創建本地分支fromdevelop git checkout -b fromdevelop git add . git commit -m "local" git checkout -b local/dev //切換到遠程分支. git checkout dev git clean_git clean -f -d-CSDN博客 git clean -f -d #刪除當前目錄下沒有被track…

RAC spfile 坑 +data INSTANCE_NUMBER thread x is mounted by another instance

RAC相關三個參數 thread reset 就可以默認 instance_number 需要單獨設置 sid‘SIDX’ cluster_database boolean TRUE SQL> alter system reset instance_number sid* scopespfile; alter system reset instance_number sid* scopespfile …

解析Torch中`Transformer`

解析torch官方代碼腳本文件&#xff1a;transformer.py。版本&#xff1a;1.9.1cu111。 首先查看《Torch中多頭注意力MultiheadAttention的中文注釋》解析&#xff1b; 最后查看下方transformer解析。 話不多說&#xff0c;看代碼吧&#xff01; import copy from typing imp…

Vue的學習之class與style綁定

<!DOCTYPE html> <html><head><meta charset"utf-8"><title>Vue的學習</title><script src"vue.js" type"text/javascript" charset"utf-8"></script></head><body><…

如何在std::map中查找元素

在std::map中查找元素可以通過幾種不同的方式完成&#xff0c;但最常用的方法是使用find成員函數。std::map是一個基于鍵值對的關聯容器&#xff0c;其中每個元素都是一個鍵值對。鍵是唯一的&#xff0c;并且用于排序和快速查找。 使用find成員函數 find成員函數接受一個鍵作…

io流 多線程

目錄 一、io流 1.什么是io流 2.流的方向 i.輸入流 ii.輸出流 3.操作文件的類型 i.字節流 1.拷貝 ii.字符流 ?3.字符流輸出流出數據 4.字節流和字符流的使用場景 5.練習 6.緩沖流 1.字節緩沖流拷貝文件 2.字符緩沖流特有的方法 1.方法 2.總結 7.轉換流基本用法…

第2集《修習止觀坐禪法要》

請打開補充講表第一面&#xff0c;附表一、念佛攝心方便法。 我們前面講到修止&#xff0c;就是善取所緣境的相貌&#xff0c;然后心于所緣&#xff0c;專一安住&#xff1b;心于所緣&#xff0c;相續安住&#xff1b;達到心一境性的目的。 站在修學凈土的角度&#xff0c;他…

FastAPI+SQLAlchemy數據庫連接

FastAPISQLAlchemy數據庫連接 目錄 FastAPISQLAlchemy數據庫連接配置數據庫連接創建表模型創建alembic遷移文件安裝初始化編輯env.py編輯alembic.ini遷移數據庫 視圖函數查詢 配置數據庫連接 # db.py from sqlalchemy import create_engine from sqlalchemy.orm import sessio…

9、程序化創意

程序化創意 程序化創意&#xff08;Programmatic Creative&#xff09;是指通過自動化的方式制作并優化廣告創意&#xff0c;以提高廣告效果。針對不同受眾的多樣化需求&#xff0c;以及同一受眾在不同場景下的消費需求&#xff0c;程序化創意能夠自動生成個性化的精準創意&am…

《C語言》預處理

文章目錄 一、預定義符號二、#define定義常量三、#define定義宏四、宏更函數的對比五、#和##1、#運算符2、##運算符 一、預定義符號 C語言設置了一些預定義符號&#xff0c;可以直接使用&#xff0c;在預處理期間進行處理的。 __FILE__//進行編譯的源文件 __LINE__//文件當前的…

在網站存在漏洞的情況下強化安全防御

一、引言 網絡安全是一個持續的戰斗&#xff0c;尤其是在網站存在已知或未知漏洞的情況下。本文將探討如何在網站存在漏洞的情況下&#xff0c;采取有效措施進行安全防御。 二、理解漏洞 首先&#xff0c;我們需要理解網站的漏洞。這些可能包括SQL注入、跨站腳本&#xff08…

【數據結構與算法】插入排序

&#x1f493; 博客主頁&#xff1a;倔強的石頭的CSDN主頁 &#x1f4dd;Gitee主頁&#xff1a;倔強的石頭的gitee主頁 ? 文章專欄&#xff1a;《數據結構與算法》 期待您的關注 ?

深入Laravel服務容器:構建靈活應用的秘訣

標題&#xff1a;深入Laravel服務容器&#xff1a;構建靈活應用的秘訣 Laravel框架的服務容器是一個強大的工具&#xff0c;它負責管理類的依賴關系和執行依賴注入&#xff08;DI&#xff09;。服務容器是Laravel依賴注入系統的核心&#xff0c;使得應用組件之間的耦合度降低&…

一周速遞|全球車聯網產業動態(2024年7月7日)

政策法規 1、7月5日&#xff0c;工業和信息化部部長金壯龍在新聞發布會上表示&#xff0c;新興產業要培育壯大。對新材料、人工智能、智能網聯新能源汽車、新型儲能、氫能、生物制造、商業航天、低空經濟等新興產業&#xff0c;要繼續用好國內大市場和豐富應用場景&#xff0c…

人工智能、機器學習、神經網絡、深度學習和卷積神經網絡的概念和關系

人工智能&#xff08;Artificial Intelligence&#xff0c;縮寫為AI&#xff09;--又稱為機器智能&#xff0c;是研究、開發用于模擬、延伸和擴展人的智能的理論、方法、技術及應用系統的一門新的技術科學。 人工智能是智能學科重要的組成部分&#xff0c;它企圖了解智能的實質…

【問題解決】 pyocd 報錯 No USB backend found 的解決方法

pyocd 報錯 No USB backend found 的解決方法 本文記錄了我在Windows 10系統上遇到的pyocd命令執行報錯——No USB backend found 的分析過程和解決方法。遇到類似問題的朋友可以直接參考最后的解決方法&#xff0c;向了解問題發送原因的可以查看原因分析部分。 文章目錄 pyoc…