PAT 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


并查集

每个人都有很多很多的爱好,如果两个人有相同的爱好,他们就属于统统一个集合。

求集合数和每个集合的人数,降序输出。

将相同爱好的人加入并查集,统计祖先的个数就可以了。

#include<bits/stdc++.h>

using namespace std;
const int N=1123;
int f[N],ans[N];
vector<int>v[N];
map<int,int>mp;

bool cmp(int a,int b)
{
    return a>b;
}

int Find(int x)
{
    if(x!=f[x])f[x]=Find(f[x]);
    return f[x];
}

void Join(int x,int  y)
{
    int fx=Find(x);
    int fy=Find(y);
    if(fx!=fy)
    {
        f[fx]=fy;
    }
}

int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0; i<=1001; i++)
    {
        f[i]=i;
    }
    for(int i=1; i<=n; i++)
    {
        int k;
        scanf("%d:",&k);
        for(int j=0; j<=k-1; j++)
        {
            int x;
            scanf("%d",&x);
            v[x].push_back(i);
        }
    }
    for(int i=1; i<=1001; i++)
    {
        if(v[i].size()>1)
        {
            for(int j=1; j<=(int)v[i].size()-1; j++)
            {
                Join(v[i][0],v[i][j]);
            }
        }
    }
    for(int i=1; i<=n; i++)
    {
        int fx=Find(i);
        if(mp.find(fx)!=mp.end())mp[fx]++;
        else mp[fx]=1;
    }
    map<int,int>::iterator it;
    int cnt=0;
    for(it=mp.begin(); it!=mp.end(); it++)
    {
        ans[cnt++]=it->second;
    }
    sort(ans,ans+cnt,cmp);
    printf("%d\n",cnt);
    for(int i=0; i<=cnt-1; i++)
    {
        if(i==cnt-1)printf("%d\n",ans[i]);
        else printf("%d ",ans[i]);
    }
    return 0;
}




评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值