小米的一道面试题:
假如已知有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; }