1107 Social Clusters (30 分)

跟着柳婼学姐学习的笔记ヾ(≧▽≦*)o


原题目: 1107 Social Clusters (30 分).

题意

社交圈中的人拥有一些相同的兴趣爱好(注意:并不是完全相同才在一个群中,而是只要有至少一个相同的爱好就在一个圈中)。

A social cluster is a set of people who have some of their hobbies in common.

给出社交网络中的总人数N(1-N-1),接着给出每人的爱好数K以及爱好ID(1~1000)。
① 输出社交圈数量(或许用set),
② 以及各圈人数(非递增)。

分析

  1. 题意分析:每个社交圈的结点是人,而不是爱好。爱好是用来判断是否处在一个社交群的;即若一个人与圈内人有至少一个相同的爱好,就会被并入这个圈中——并查集
  2. 确定了用并查集,则先写好初始化、findFather、Union。
  3. 生成社交圈:
    ①hobby[t]表示任意一个爱好为t的人的编号——不妨用录入的第一个喜欢t的人的编号。
    合并: 对于编号为i的人,录入其爱好t,则需要将 i 合并到同样喜欢 t 的人的圈子里——(ⅰ) findFather(hobby[t])就是喜欢t的人所处的社交圈的根结点,(ⅱ) 合并 i 与 同好圈。
  4. 计算社交圈的个数和圈内人数,即根结点个数和同根结点的结点个数——① 先用数组isRoot按下标统计同根结点的结点个数,② 再用计数器cnt计算数组isRoot中非0元素个数。

知识点

  1. 并查集的应用——将有相同爱好的人合并到同一个社交圈中;写好三个基本操作,学会合理利用。
  2. 静态数组——利用随机访问性,可以 按下标 记录统计个数

CODE

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
vector<int> father, isRoot;
bool cmp(int a, int b){
    return a>b;  //递减排序
}
int findFather(int x);  //找结点x的根结点
void Union(int a, int b);  //合并结点a和b所在集合
int main()
{
    int n, k, t, cnt = 0;
    int hobby[1001] = {0};  //hobby[t]表示任意一个喜欢t爱好的人的编号
    cin >> n;
    father.resize(n+1);
    isRoot.resize(n+1);
    for ( int i=1; i<=n; i++ )
        father[i] = i;   //并查集初始化,初始时各自独立,各自成根结点
    for ( int i=1; i<=n; i++ ){
        cin >> k;
        string s;
        cin >> s;  //消耗掉一个冒号
        for ( int j=0; j<k; j++ ){
            cin >> t;
            if ( hobby[t]==0 )
                hobby[t] = i;
            //将爱好为t的人所处社交群的根结点与当前人的编号i结点合并
            Union(i, findFather(hobby[t])); 
        }
    }
    for ( int i=1; i<=n; i++ )
        isRoot[findFather(i)]++;   //记录同一个根结点的社交群中的总人数
    for ( int i=1; i<=n; i++ ){
        if ( isRoot[i]!=0 )
            cnt++;  //记录社交群的个数
    }
    cout << cnt << endl;
    sort(isRoot.begin(), isRoot.end(), cmp);
    for ( int i=0; i<cnt; i++ ){
        cout << isRoot[i];
        if ( i!=cnt-1 ) cout << " ";
    }
    
    return 0;
}
int findFather(int x){
    int a = x;
    while( x!=father[x] )
        x = father[x];
    while( a!=father[a] ){
        int z = a;
        a = father[a];
        father[z] = x;
    }
    return x;
}
void Union(int a, int b){
    int faA = findFather(a);
    int faB = findFather(b);
    if ( faA!=faB )
        father[faA] = faB;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值