PAT - 1107. Social Clusters (30) 并查集

1107.Social Clusters (30)

When register on a social network, you are always asked to specify your hobbies in order to find some potential friends with the same hobbies. A “social cluster” is a set of people who have some of their hobbies in common. You are supposed to find all the clusters.

Input Specification:

Each input file contains one test case. For each test case, the first line contains a positive integer N (<=1000), the total number of people in a social network. Hence the people are numbered from 1 to N. Then N lines follow, each gives the hobby list of a person in the format:

Ki: hi[1] hi[2] … hi[Ki]

where Ki (>0) is the number of hobbies, and hi[j] is the index of the j-th hobby, which is an integer in [1, 1000].

Output Specification:

For each case, print in one line the total number of clusters in the network. Then in the second line, print the numbers of people in the clusters in non-increasing order. The numbers must be separated by exactly one space, and there must be no extra space at the end of the line.

Sample Input:

8
3: 2 7 10
1: 4
2: 5 3
1: 4
1: 3
1: 4
4: 6 8 1 5
1: 4

Sample Output:

3
4 3 1

题意

大体意思就是说有n个人
每个人有k个hobby
然后有相同hobby的人就属于一类人
求 一共有几个分类以及每个聚类中有多少人
很明显并查集
不过时间充足我暴力了……

code

/*
另类并查集思想
并查集的节点(hobby)不带秩
而使用peoNum来记录节点的'秩'
进而暴力累加某一类的peoNum
*/

#include <bits/stdc++.h>

using namespace std;

int peoNum[1110];  /// 某个hobby代表的人的数量
int root[1110];    /// 并查集-父节点
bool status[1110]; /// status 证明是否有这个hobby序号
int ans[1110];     /// 每个'聚类'中人的数量

void init()
{
    for(int i=0; i<=1000; i++)
    {
        root[i] = i;
        peoNum[i] = 0;
        status[i] = 0;
        ans[i] = 0;
    }
}

int fd(int x)
{
    if(x != root[x])
    {
        root[x] = fd(root[x]);
    }
    return root[x];
}

void un(int x,int y)
{
    x = fd(x);
    y = fd(y);
    root[x] = y;
}

bool cmp(int x,int y)
{
    return x >= y;
}

int main()
{
    char c; /// 吃冒号....
    int n,i,j,k,x,y;
    vector <int> father; ///保存根的信息

    init();
    cin>>n;
    for(i=1; i<=n; i++)
    {
        cin>>k>>c;
        cin>>y;
        status[y] = 1;
        peoNum[y]++; /// 第一个节点就可以代表一个人 这样不会记录重复的人数
        for(j=2; j<=k; j++)
        {
            cin>>x;
            status[x] = 1;
            un(y,x);
        }
    }
    int cnt = 0; /// 记录'聚类'
    for(i=1; i<=1110; i++)
    {
        if(status[i]==1 && root[i] == i)
        {
            cnt++;
            father.push_back(i);
        }
    }
    cout<<cnt<<endl;
    for(i=0; i<father.size(); i++) /// 暴力-找父节点所在聚类的人数加和
    {
        for(j=0; j<1110; j++)
        {
            if(status[j] == 1 && fd(j) == father[i])
            {
                ans[i] += peoNum[j];
            }
        }
    }
    sort(ans,ans+father.size(),cmp);
    for(i=0; i<father.size(); i++)
    {
        if(i == 0)
        {
            cout<<ans[i];
        }
        else
        {
            cout<<" "<<ans[i];
        }
    }
    cout<<endl;
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值