小米的一道面试题:
假如已知有n个人和m对好友关系,如果两个人是直接或者间接有好友关系,则认为他们属于同一个朋友圈。写程序判断里面有多少朋友圈。
例如:
n = 5, m = 3 r = {(1,2), (2, 3), (4, 5)} 1 2 3 是一个朋友圈, 4 5 是一个朋友圈。
所以输出是2
这道题用并查集来求解就非常容易了。关于并查集的内容,这篇文章写得非常好:
http://blog.csdn.net/dm_vincent/article/details/7655764#reply
根据这篇文章,写了一个求解方法,代码如下:
class UnionFind {
public:
UnionFind(int n) : cnt(n)
{
id = new int[n];
for (int i = 0; i < n; i++)
id[i] = i;
size = new int[n];
for (int i = 0; i < n; i++)
size[i] = 1;
}
~UnionFind()
{
delete[] id;
delete[] size;
}
// 返回连通组的个数
int count()
{
return cnt;
}
// 查找一个节点属于哪个组
int findSet(int a)
{
if (id[a] == a)
return a;
else
return id[a] = findSet(id[a]); // 查找的同时提高节点的高度
}
bool isSameSet(int a, int b)
{
int x = findSet(a); // 查找a的组号
int y = findSet(b); // 查找b的组号
return x == y; // 判断组号是否相同
}
void Union(int a, int b)
{
int x = findSet(a);
int y = findSet(b);
if (x != y)
{
if (size[x] < size[y])
{
id[x] = y;
size[y] += size[x];
}
else
{
id[y] = x;
size[x] += size[y];
}
cnt--; // 合并后组的数量-1
}
}
private:
int *id;
int *size;
int cnt;
};
int main()
{
UnionFind friends(5);
friends.Union(0, 1);
friends.Union(1, 2);
friends.Union(3, 4);
cout << "朋友圈数目:" << friends.count() << endl;
system("pause");
return 0;
}
运行结果: