• 1362:家庭问题(family)


    【题目描述】
    有n个人,编号为1,2,……n,另外还知道存在K个关系。一个关系的表达为二元组(α,β)形式,表示α,β为同一家庭的成员。

    当n,k和k个关系给出之后,求出其中共有多少个家庭、最大的家庭中有多少人?

    例如:n=6,k=3,三个关系为(1,2),(1,3),(4,5)

    此时,6个人组成三个家庭,即:{1,2,3}为一个家庭,{4,5}为一个家庭,{6}单独为一个家庭,第一个家庭的人数为最多。

    【输入】
    第一行为n,k二个整数(1≤n≤100)(用空格分隔);

    接下来的k行,每行二个整数(用空格分隔)表示关系。

    【输出】
    二个整数(分别表示家庭个数和最大家庭人数)。

    【输入样例】
    6 3
    1 2
    1 3
    4 5
    【输出样例】
    3 3

    分析

    1. 此题用并查集,有关并查集学习见:图论——并查集
    2. 需要理解f[i]和find(i)的区别及作用;
    • 在进行两个点是否存在关系的判断时,用的是find(x)、find(y),看他们祖先是否相同
    • 在进行连通分量的确定时,是用f[i]=i,有几个这样的点(也就是根节点),来确定连通分量数
    1. 此题用一个数组a去保存下标为i结点的孩子数(通过让find(i)为索引,然后值++),就能通过遍历这个数组来找到最大家庭数;然后根节点数,也就是f[i]==i的个数,就是家庭个数,也是连通块的个数;
    #include 
    
    using namespace std;
    int f[105];
    int a[105];//结点下的孩子数量
    int n, k, cnt, mx;
    
    void init() {
        //由于从1编号的,所以for就不从0了
        for (int i = 1; i <= n; ++i) {
            f[i] = i;
        }
    }
    
    int find(int x) {
        if (f[x] == x)
            return x;
        //递归返回时,不断将根节点作为每一个结点的父亲
        return f[x] = find(f[x]);
    }
    
    //合并两个结点
    void merge(int a, int b) {
        a = find(a);
        b = find(b);
        f[a] = b;
    }
    
    int main() {
        cin.tie(0);
        cin >> n >> k;
        init();
        for (int i = 0; i < k; ++i) {
            int x, y;
            cin >> x >> y;
            merge(x, y);
        }
        for (int i = 1; i <= n; ++i) {
            a[find(i)]++;
            if (f[i] == i) {
                //这是查根节点的数目,可以说明有几个家庭数
                cnt++;
            }
        }
        for (int i = 1; i <= n; ++i) {
            mx = max(mx, a[i]);
        }
        cout << cnt << " " << mx;
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
  • 相关阅读:
    多目标权重融合方式
    【JMeter】Beanshell介绍
    网络安全(黑客)技术——自学2024
    springboot接收前端传值的几种方式
    商品期货一手是多少(商品期货一手是多少吨)
    SSL VPN综合实验
    C#学习笔记---异常捕获和变量运算符
    优化风控模型特征变量池,试一下这种实操方法
    滴滴2023秋招笔试 老张的美数课 (C++ DP)
    信息学奥赛一本通-编程启蒙3103:练18.3 组别判断
  • 原文地址:https://blog.csdn.net/weixin_51995229/article/details/126349441