C++實現並查集
阿新 • • 發佈:2019-01-09
將N個不同的元素分成一組不相交的集合。
開始時,每個元素就是一個集合,然後按規律將兩個集合進行合併。
假如已知有n個人和m對好友關係(存於陣列r),如果兩個人是直接的或間接的好友關係(好友的好友的好友....),則認為他們屬於同一好友圈,請求出這n個人中有幾個好友圈。
例如:n=5,m=3,r={{1,2},{2,3},{4,5}},表示有5個人,1和2是好友,2和3是好友,4和5是好友,則1.2.3屬於一個朋友圈,4.5屬於一個另朋友圈,結果為兩個朋友圈。
最後請分析所寫程式碼的時間、空間複雜度。
這個題用利用並查集實現會比較簡易和高效!
#define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<stdlib.h> using namespace std; class UnionFindSet { public: UnionFindSet(size_t size) :_array(new int[size]) , _size(size) { memset(_array, -1, sizeof(int)*_size); } ~UnionFindSet() { if (_array != NULL) { delete[] _array; } } void Merge(int root1, int root2) { while (_array[root2] >= 0) { root2 = _array[root2]; } while (_array[root1] >= 0) { root1 = _array[root1]; } _array[root1] += _array[root2]; _array[root2] = root1; } int Find(int child) { while (_array[child] >= 0) { child = _array[child]; } return child; } void print() { for (int i = 0; i < _size; ++i) { cout << _array[i] << " "; } cout << endl; } int friends(int n, int m, int r[][2]) { UnionFindSet uf(n + 1); for (int i = 0; i < m; i++) { int first = r[i][0]; int second = r[i][1]; uf.Merge(first, second); } uf.print(); int count = 0; for (int i = 1; i <= n; i++) { if (uf._array[i] < 0) { count++; } } return count; } private: int* _array; size_t _size; }; void test() { UnionFindSet us(10); us.Merge(0, 6); us.Merge(0, 7); us.Merge(0, 8); us.Merge(1, 4); us.Merge(1, 9); us.Merge(2, 3); us.Merge(2, 5); us.Merge(0, 4); us.print(); cout << "4的朋友樹的父節點是" << us.Find(4) << endl; int n = 5; int m = 3; int r[][2]= { { 1, 2 }, { 2, 3 }, { 4, 5 } }; int Frindcirle = us.friends(n, m, r); cout << Frindcirle << endl; } int main() { test(); system("pause"); return 0; }