将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;
}