题解 | 第一题

第一题

https://www.nowcoder.com/practice/7c29cdfa28274c86afc9e88c07448a10

#include <iostream>
#include <map>

using std::cout;
using std::endl;
using std::map;

map<int, int> father;
map<int, int> height;

// 找到节点n的根节点,并把沿途节点的father节点全部设为root
// 即具有压缩路径的功能
int FindRoot(int n) {
    if (father[n] != n) { // 若当前节点不是本集合的根节点
        father[n] = FindRoot(father[n]);
        /* height[n]不用管,因为我们只关心根节点的高度(也就是本棵树/本集和的高度) */
    }
    return father[n];   // 本集和的根节点
}

void Union(int n1, int n2) {
    int root1 = FindRoot(n1);
    int root2 = FindRoot(n2);
    if (root1 == root2) // 两个节点本就在同一个集合中
        return; // 直接返回就行
    // 接下来说明两节点属于两个集合,就要涉及到集合合并操作(矮树合并到高树中)
    else if (height[root1] > height[root2]) {
        father[root2] = root1;
    } else if (height[root1] < height[root2]) {
        father[root1] = root2;
    } else { // 两棵树同样高
        father[root2] = root1;  // 将2树合并到1树中
        height[root1]++;    // 1树的高度必然+1
    }
}

int main() {
    int n1, n2;
    while (scanf("%d%d", &n1, &n2) != EOF) {
        if (father.count(n1) == 0) { // 该节点为新节点
            father[n1] = n1;    //  将该节点作为新的集合的根节点
            height[n1] = 1; // 新的集合的高度为1
        }
        if (father.count(n2) == 0) { // 同上
            father[n2] = n2;
            height[n2] = 1;
        }
        Union(n1, n2);  // 将两个节点所在的集合进行合并
    }

    // 计算连通分量的个数
    int cnt = 0;    // 记录联通分量的个数(father[n] == n)
    for (auto& elem : father) {
        if (elem.first == elem.second)
            ++cnt;
    }
    cout << cnt << endl;

    return 0;
}


全部评论

相关推荐

迷茫的大四🐶:💐孝子启动失败,改为启动咏鹅
点赞 评论 收藏
分享
热爱生活的咸鱼在吃瓜:个人建议,项目太简单了,实习干的活都是测试的活,反正又没人知道你实习干啥了,你懂吧
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务