【超易懂】并查集
一、適用的問題描述:
某家族人口過于龐大,要判斷兩個是否是親戚不容易。先給出已知的親戚關系圖,求任意給出的兩人是否為親戚關系。規定親戚有傳遞性。
樣例輸入/輸出:
6 5 3 (說明:6個人,5個親戚關系,3組判斷)1 2 1 5 3 4 5 2 1 31 4 Yes 2 3 Yes 5 6 No二、并查集圖文解釋:
基礎知識可參考:
http://wenku.baidu.com/link?url=GdU6OI4eoEOOk9UvEYvsy9enrCNwILxFxBVOjblSrk_dCG6nThAmrooh_saGYRGZywzNCpq08iMdAmvp8WG5bV6zCyGu_lG0lLpjnpNYS1W
三、下面的程序,和上圖原理稍有不同。不是用最小元素標記,請讀者仔細揣摩。
參考程序(C++版)
#define _CRT_SECURE_NO_DEPRECATE //一定要放最前面才可起作用 #include <stdio.h> //可用cstdio代替 #define MAX 5001 //元素個數 int P[MAX]; //標記數組 using namespace std; //命名空間class MyClass{ //類聲明public:MyClass(int N);//構造函數void merge(int p, int q);//加入關系圈bool isConnected(int p, int q);//判斷是否在同一個圈中int count();//計算有多少個圈//int find(int p);private:int n;//數據成員};//如兩值根的指向一致,則為同一圈bool MyClass::isConnected(int p, int q){if (P[p] == P[q]) return true; else return false;}//void MyClass::merge(int p, int q){int p_id = P[p];int q_id = P[q];if (!this->isConnected(p,q)){ //通過之前關系判斷親緣int i; for (i = 1; i < this->n; i++){if (P[i] == p_id) P[i] = q_id; //右值鏈到左值上,他們有同一根}}}MyClass::MyClass(int N){this->n = N;int i;for (i = 1; i < N; ++i) P[i] = i;}int main(){int n, m, p, i, Mi, Mj;scanf("%d%d%d",&n,&m,&p);MyClass mc(n);for (i = 0; i < m; i++){scanf("%d%d", &Mi,&Mj);mc.merge(Mi,Mj);}for (i = 0; i < p; ++i){scanf("%d%d",&Mi,&Mj);if (mc.isConnected(Mi, Mj)) printf("Yes");else printf("No");}}運行結果:
歡迎繼續交流,蘭理工Q:316190672
總結
- 上一篇: c++中类的申明和定义
- 下一篇: 【小米笔试题】朋友圈问题-并查集解法