PAT1107 Social Clusters(并查集)

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:

K​i​​: h​i​​[1] h​i​​[2] ... h​i​​[K​i​​]

where K​i​​ (>0) is the number of hobbies, and h​i​​[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

题意:有一群人每个人都有各自的兴趣,如果兴趣有重叠的部分就认为是同一个group。现给定每个人的兴趣list,问你共有几个group及每个group的人数(从大到小输出)

解法:并查集

还是维护以人为结点的森林,这里还需要一个数组去维护每个兴趣对应的“头”。这其实是在每一次更新的时候处理。

一开始初始化为0,如这个兴趣还没有人有,则将值赋为当前的人的编号。否则就将该兴趣对应的人和当前的人进行unite。

再将所有的兴趣对应的人更新为当前的”头“ 。(其实可能不用、不过这样更明确一点)

然后就可以了,统计每个人群的人数,这里为了方便用了priority_queue。

#include 
#define pii pair
#define ll long long
#define eps 1e-5
using namespace std;
const int oo = 0x7fffffff;
const int maxn = 1e4 + 10;
int par[maxn];
int hobby[maxn];
void init(int n)
{
    for(int i = 1; i <= n; i++)
        par[i] = i;
}
int f(int x)
{
    if(x == par[x])
        return x;
    return par[x] = f(par[x]);
}
void unite(int x, int y)
{
    x = f(x);
    y = f(y);
    par[x] = y;
}
int main()
{
    //    freopen("/Users/vector/Desktop/testdata.in", "r", stdin);
//    ios::sync_with_stdio(false);
//    cin.tie(0);
    int n;
    scanf("%d", &n);
    init(n);
    for(int i = 1; i <= n; i++)
    {
        int m;
        scanf("%d:", &m);
        while(m--)
        {
            int t;
            scanf("%d", &t);
            if(hobby[t] == 0)
                hobby[t] = i;
            else
            {
                unite(i, hobby[t]);//如果当前兴趣已经存在则进行合并
                hobby[t] = f(i);
            }
        }
    }
    map q;
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= n; j++)
            if(f(j) == i)
                q[i]++;
    }
    priority_queue ans;
    for(auto idx: q)
        ans.push(idx.second);
    int cnt = (int)ans.size();
    printf("%d\n", cnt);
    while(ans.size())
    {
        printf("%d", ans.top());
        ans.pop();
        if(cnt > 1)
            putchar(' ');
        else
            putchar('\n');
        cnt--;
    }
    
    return 0;
}

 

你可能感兴趣的:(并查集)