PAT【甲级】1107

本文介绍了PAT甲级1107题的解题思路与代码实现,主要涉及并查集数据结构的应用。通过建立并查集,将有相同爱好的人归为同一社交网络,最终统计社交网络的数量。关键在于正确使用并查集进行路径压缩和求解团体人数。注意避免在统计人数时的路径未压缩错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:PAT【甲级】1107
题目简述:有n个人,每个人喜欢k个活动,如果两个人有任意⼀个活动相同,就称为他们处于同一个社交网络。求这n个人⼀共形成了多少个社交网络。

#include<bits/stdc++.h>
using namespace std;

int father[1001], exist[1001], hobby[1001];
vector<int> ans;

int findFather(int a){
    int x = a;
    while(x != father[x]) x = father[x];
    while(a != father[a]){//压缩路径
        int t = father[a];
        father[a] = x;
        a = t;
    }
    return x;
}

void Union(int a, int b){
    int x1 = findFather(a), x2 = findFather(b);
    father[x1] = x2;
}

int main(){
    int n;
    cin >> n;
    for (int i = 0; i < 1001;i++)//初始化并查集
        father[i] = i;
    for (int i = 0; i < n;i++){
        int c, t, pre;
        scanf("%d:%d", &c, &pre);
        exist[pre] = 1;//标记存在出现
        hobby[i] = pre;//存储第i个成员的一个爱好
        for (int j = 1; j < c;j++){
            cin >> t;
            Union(t, pre);
            pre = t;
            exist[t] = 1;//标记存在出现
        }
    }
    /*代码截止到这里,并查集已经建立完成;但是各节点路径压缩并没有全部完成*/
    for (int i = 0; i < n; i++)
        exist[findFather(hobby[i])]++;//记录人数
    for (int i = 0; i < 1001;i++)
        if(exist[i] > 1)
            ans.push_back(exist[i] - 1);//添加爱好相同的团体人数
    sort(ans.begin(), ans.end());
    cout << ans.size() << endl << ans[ans.size() - 1];
    for (int i = ans.size() - 2; i >= 0; i--)
        cout << " " << ans[i];
    cout << endl;
    return 0;
}

题目分析

拿到这个题目,就晓得是需要使用并查集的知识来解决,这样会把爱好都分成不同的团体,然后再去映射到不同的人,最后统计人数即可。

我这里是使用exist数组来充当记录的作用,因为爱好都已经分好集合了,那么我们现在开始从每个人出发,这时也就用到了之前记录的变量hobby[i],由于并查集的建立,这个爱好的取值可以是当前人的任意一个爱好,便于代码编写,这里选择第一个爱好。然后便去找寻其父亲,在对应位置处该爱好人数加1

最后输出即可。

坑点

对于

/*代码截止到这里,并查集已经建立完成;但是各节点路径压缩并没有全部完成*/
    for (int i = 0; i < n; i++)
        exist[findFather(hobby[i])]++;//记录人数

这部分代码,切不可写成以下样式,原因就是注释。

for (int i = 0; i < n; i++)
    exist[father[hobby[i]]]++;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值