题目来源:PAT (Advanced Level) Practice
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
words:
Clusters 集群,群集 register 登记,注册 potential 潜在的 network 网
题意:
给出n个人的爱好列表(爱好用1-1000的数字表示),具有相同爱好的人认为是一个集群,而且,若A和B是一个集群,B和C是一个集群,那么则A、B、C是一个集群;求出集群的个数和每个集群的人数;因此使用并查集来处理;
思路:
1. 使用一个hobby[1001]数组记录第一个开始喜欢该爱好的人,若还没有人喜欢该爱好,则为0;
2. 使用一个ab[N+1]数组表示并查集,即将相同爱好的人连接在一起 ;ab[i]初始默认为i,及每个人最开始都是独立的;
3. 输入每个人的爱好;每输入一个人的爱好,若该爱好尚无人喜欢,则将该人记录其中,若已经有人喜欢,则判断这两个人(正在输入的人和第一个喜欢该爱好的人)是否属于同一集群,即是否根相同;若不相同则合并;
4. 使用集合se来统计ab[]中根的个数,即集群的个数;
5. 遍历集合se中的所有元素(即根),统计每个根下的结点数(包括根),即每个集群的人数;
6. 输出集群的个数以及按照降序输出每个集群的人数;
//PAT ad 1107 Social Clusters
#include <iostream>
using namespace std;
#include <set>
#include <vector>
#include <algorithm>
#define N 1000
int hobby[1000+1]; //记录第一个开始喜欢该爱好的人,若还没有人喜欢该爱好,则为0
int ab[N+1]; //0号元素不用,将相同爱好的人连接在一起
int find(int x) //查找x的根
{
if(x==ab[x])
return x;
return ab[x]=find(ab[x]);
}
int main()
{
int n,i;
cin>>n;
char c;
int k,x;
for(i=1;i<=n;i++) //输入
{
cin>>k>>c; //爱好个数
ab[i]=i; //初始指向自己
while(k--)
{
cin>>x; //第i个人的爱好
if(hobby[x]==0) //该爱好尚无人喜欢
hobby[x]=i;
else
{
int fa=find(hobby[x]); //寻找喜欢爱好x的第一个人的根;
int fb=find(i); //寻找i的根,或 fb=i;
if(fa!=fb) //有不同的根,则合并
{
ab[fa]=fb; //将fa指向fb
}
}
}
}
set<int> se;
for(i=1;i<=n;i++) //统计所有的根
{
x=find(i);
se.insert(x);
}
cout<<se.size()<<endl; //the total number of clusters,即根的个数
vector<int> ans;
for(auto w:se) //统计每个根下的结点的数(包括根)
{
int c=0;
for(i=1;i<=n;i++)
if(ab[i]==w)
c++;
ans.push_back(c); //the numbers of people in the clusters
}
sort(ans.begin(),ans.end());
for(i=ans.size()-1;i>0;i--) //输出
cout<<ans[i]<<" ";
cout<<ans[i]<<endl;
return 0;
}