朋友圈问题

#include <iostream>
#include <vector>

using namespace std;

// 并查集的查找操作
int find(vector<int>& parent, int x) {
    if (parent[x] != x) {
        parent[x] = find(parent, parent[x]); // 路径压缩
    }
    return parent[x];
}

// 并查集的合并操作
void unionSets(vector<int>& parent, vector<int>& rank, int x, int y) {
    int rootX = find(parent, x);
    int rootY = find(parent, y);
    if (rootX != rootY) {
        // 按秩合并
        if (rank[rootX] > rank[rootY]) {
            parent[rootY] = rootX;
        } else if (rank[rootX] < rank[rootY]) {
            parent[rootX] = rootY;
        } else {
            parent[rootY] = rootX;
            rank[rootX] += 1;
        }
    }
}

int main() {
    int N, M;
    cin >> N >> M;

    vector<int> parent(N + 1);
    vector<int> rank(N + 1, 0);

    // 初始化并查集
    for (int i = 1; i <= N; ++i) {
        parent[i] = i;
    }

    for (int i = 0; i < M; ++i) {
        int Mi;
        cin >> Mi;
        int firstStudent;
        cin >> firstStudent;
        for (int j = 1; j < Mi; ++j) {
            int student;
            cin >> student;
            unionSets(parent, rank, firstStudent, student);
        }
    }

    // 统计每个代表所代表的学生数量
    vector<int> count(N + 1, 0);
    for (int i = 1; i <= N; ++i) {
        int root = find(parent, i);
        count[root]++;
    }

    // 找到数量最多的代表
    int maxFriends = 0;
    for (int i = 1; i <= N; ++i) {
        if (count[i] > maxFriends) {
            maxFriends = count[i];
        }
    }

    cout << maxFriends << endl;

    return 0;
}
在书写这个代码的过程当中,我们可能会遇得到的问题总结,可以帮助我们更好的理解代码的书写逻辑。

1)忘记初始化parent和rank数组,导致合并或查找的时候出现问题,导致程序报错。

请加附页。注意学生的编号是从1开始的,但是数组未留出parent[0]的位置。我们通过正确的初始化代码解决该问题,对于数组的大小设置未N+1,索引0不用

(2)出现合并逻辑错误,合并时未正确更新rank,导致树退化成链表,查找效率低。我们通过按秩合并这个方法进行元素之间的合并,可以解决这个问题。

(3)路径压缩未生效,当我们在查找的时候,没有及时更新父节点,导致后续的查找仍然很缓慢,我通过递归路径的方法进行压缩可以避免这个问题的出现。

(4)统计朋友圈大小错误,在直接遍历parent数组统计当中,没有调用find,导致未压缩的父节点影响结果,我通过find函数进行获取根节点,来解决该问题

(5)输入的数据有误,当我粗心出现俱乐部内容的正确的输入,漏写数据或者错误合并等问题,采取利用for循环进行逐行读取并合并

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值