有n位同学要玩游戏,要求分组方案中将所有得好友组合都被分在一组。
输入格式:
第一行输入两个数n和m,1<=n, m <= 1000000。
接下来输入m行,每行输入两个数a和b,表示编号a和编号b的同学是好友关系,0<=a, b <= n-1。
输出格式:
输出一行,表示最多可以分成多少组。
样例1:
输入:
5 2
0 2
2 3
输出:
3
样例说明:
第一组:编号为0、2 、3的同学
第二组:编号为1的同学
第三组:编号为4的同学
代码实现:
#include <iostream>
using namespace std;
class DisjointSet {
private:
int *father, *rank, size;
public:
DisjointSet(int _size) {
size = _size;
father = new int[size];
rank = new int[size];
for (int i = 0; i < size; ++i) {
father[i] = i;
rank[i] = 0;
}
}
~DisjointSet() {
delete[] father;
delete[] rank;
}
int find_set(int node) {
if (father[node] != node) {
//将递归调用的返回值赋给当前结点的father,即指向树根结点
father[node] = find_set(father[node]);
}
//返回树根结点
return father[node];
}
bool merge(int node1, int node2) {
int ancestor1 = find_set(node1);
int ancestor2 = find_set(node2);
if (ancestor1 != ancestor2) {
if (rank[ancestor1] > rank[ancestor2]) {
swap(ancestor1, ancestor2);
}
father[ancestor1] = ancestor2;
rank[ancestor2] = max(rank[ancestor1] + 1, rank[ancestor2]);
return true;
}
return false;
}
int find_tree_num() {
int num = 0;
for (int i = 0; i < size; ++i) {
if (father[i] == i) {
num++;
}
}
return num;
}
};
int main() {
int n, m, a, b;
cin >> n >> m;
DisjointSet dsu(n);
for (int i = 0; i < m; ++i) {
cin >> a >> b;
dsu.merge(a, b);
}
cout << dsu.find_tree_num() << endl;
return 0;
}