1107 Social Clusters (30point(s)) - C语言 PAT 甲级

1107 Social Clusters (30point(s))

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 个人的爱好,若有两个人有相同的爱好,则这两个人视为在同一社交圈,求所有人构成了多少社交圈数量,并输出每个社交圈的人数,从大到小排序

设计思路:

并查集

  • 社交圈是人组成的,爱好仅是判断两人是否在同一社交圈的媒介
  • hobby[] 数组记录当前爱好有无人喜欢
    • 若还没有,自己占据此爱好,当作此社交圈的祖先
    • 若有人,则把自己加入此社交圈
  • 对每个人进行遍历,记录组成了多少社交圈,和每个社交圈的人数
编译器:C (gcc)
include <stdio.h>

int cmp(const void *a, const void *b)
{
        return *((int *)b) - *((int *)a);
}

int father[1010], rank[1010];

void makeset()
{
        int i;
        for (i = 0; i < 1010; i++) {
                father[i] = i;
                rank[i] = 0;
        }
}

int getfather(int v)
{
        if (father[v] == v)
                return v;
        father[v] = getfather(father[v]);
        return father[v];
}

void judge(int x, int y)
{
        int fx = getfather(x);
        int fy = getfather(y);
        if (rank[fx] > rank[fy]) {
                father[fy] = fx;
        } else {
                father[fx] = fy;
                if (rank[fx] == rank[fy])
                        rank[fy]++;
        }
}

int main(void)
{
        int n;
        int hobby[1010] = {0}, result[1010] = {0};
        int i, j, k, a;

        makeset();
        scanf("%d", &n);
        for (i = 1; i <= n; i++) {
                scanf("%d:", &k);
                while (k--) {
                        scanf("%d", &a);
                        if (hobby[a] == 0)
                                hobby[a] = i;
                        else
                                judge(hobby[a], i);
                }
        }
        for (i = 1; i <= n; i++)
                result[getfather(i)]++;
        qsort(result + 1, n, sizeof(result[0]), cmp);
        for (i = 1; i <= n && result[i] > 0; i++)
                ;
        printf("%d\n", i - 1);
        for (j = 1; j < i; j++)
                printf("%s%d", j > 1 ? " " : "", result[j]);
        return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值