并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中的这种数据结构叫做并查集。
已知有N个人和m对好友关系,如果这两个人士直接好友或者间接的好友(好友的好友….)则认为他们属于同一个朋友圈,n=5,m=3,r={{1,2},{2,3},{4,5}}求出这n个人里一共有多少个朋友圈。
首先解决这个问题我们需要考虑到它的时间复杂度问题,使用并查集就能很好的解决。
#include<iostream>
#include<stdlib.h>
#include<vector>
using namespace std;
class UnionSet
{
public:
UnionSet(int n)
{
v.resize(n+1);
for (int i = 0; i <= n; ++i)
{
v[i] = -1;
}
}
int FindRoot(int x)
{
return v[x];//返回它的根
}
void Merge(int x, int y)
{
int root1 = FindRoot(x);
int root2 = FindRoot(y);
if ((root1 == root2) && root1 == -1)//如果他属于一个单独的集合,不属于别的集合
{
v[y] = x;
v[x] += -1;
}
else if (root1 != root2)//属于别的集合
{
if (root1 > 0)
{
v[y] = v[x];
v[root1] += -1;
}
else
{
v[x] = v[y];
v[root2] += -1;
}
}
}
int Size()
{
return v.size();
}
int Count()
{
int n = Size();
int count = 0;
for (int i = 0; i < n; ++i)
{
if (v[i] <0)
{
++count;
}
}
return count-1;
}
protected:
vector<int> v;
};
int friends(int n, int m, int arr[][2])
{
UnionSet u(n);
for (int i = 0; i < m; ++i)
{
u.Merge(arr[i][0], arr[i][1]);
}
int count = u.Count();
return count;
}
int main()
{
int arr[][2] = { { 1, 2 }, { 2, 3, }, { 4, 5 }, { 6, 7 } };
cout<<friends(7, 4, arr);
system("pause");
return 0;
}