十、森林与并查集---(7)游戏分组

有n位同学要玩游戏,要求分组方案中将所有得好友组合都被分在一组。

输入格式:

第一行输入两个数n和m,1<=n, m <= 1000000。

接下来输入m行,每行输入两个数a和b,表示编号a和编号b的同学是好友关系,0<=a, b <= n-1。

输出格式:

输出一行,表示最多可以分成多少组。

样例1:

输入:

5 2

0 2

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值