1107. Social Clusters (30) 并查集

来源:互联网 发布:照片管理的软件 编辑:程序博客网 时间:2024/06/06 01:25

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:
83: 2 7 101: 42: 5 31: 41: 31: 44: 6 8 1 51: 4
Sample Output:
34 3 1
并查集:

思路就是每个人纪录自己的第一个hobby。后面的hobby都与第一个hobby合并

然后遍历每个人的第一个hobby,输出

#include<cstdio>#include<cmath>#include<algorithm>#include<iostream>#include<cstring>#include<queue>#include<vector>#include<set>#include<map>#include<stack>using namespace std;const int INF=1<<29;int n;int father[10001]; int find(int x){if(x==father[x]) return x;return father[x]=find(father[x]);}bool cmp(int a,int b){return a>b;}int main(){cin>>n;int a[10001];for(int i=1;i<=1000;i++) father[i]=i;set<int> s; for(int i=1;i<=n;i++){int num;scanf("%d:",&num);int fz; scanf("%d",&fz);a[i]=fz;fz=find(fz);for(int j=1;j<num;j++){int nu;    scanf("%d",&nu);    nu=find(nu);    father[nu]=fz;}} map<int,int> ma;int out[10001]={0},cnt=0;for(int i=1;i<=n;i++){ma[find(a[i])]++;}for(map<int,int>::iterator it=ma.begin();it!=ma.end();it++){out[cnt++]=it->second;}sort(out,out+cnt,cmp); cout<<cnt<<endl; for(int i=0;i<cnt;i++){    if(i==0) printf("%d",out[i]);    else printf(" %d",out[i]);} return 0;}


在网上看到别人的代码,思路是跟我相反的:

第一次出现的hobby绑定给当前的人,后面出现这个hobby,直接两个人合并;

最后遍历人,输出

#include <iostream>  #include <algorithm>  #include <cstdio>  #include <cstdlib>  #include <cstring>  #include <string>  #include <vector>  #include <queue>  #include <stack>    using namespace std;    bool comp(int a,int b)  {      return a>b;  }    int power[1010]={0};  int book[1010]={0};  int father[1010];    int findRoot(int x)//找到集合的根  {      while(x!=father[x])      {          x=father[x];      }      return x;  }  void init(int n)//初始化  {      int i;      for(i=1;i<=n;i++)          father[i]=i;  }  void Union(int a,int b)//合并元素a,b所在的集合  {      int roota,rootb;      roota=findRoot(a);      rootb=findRoot(b);      father[roota]=rootb;  }  int main()  {      //freopen("in.txt","r",stdin);        int N;      cin>>N;      init(N);      for(int i=1;i<=N;i++)      {          int k;          scanf("%d:",&k);          int j;          for(j=1;j<=k;j++)          {              int h;              cin>>h;              if(book[h]==0)              {                  book[h]=i;              }              else              {                  Union(i,book[h]);              }          }      }        int cou=0;      for(int i=1;i<=N;i++)      {          if(father[i]==i)              cou++;      }      cout<<cou<<"\n";        for(int i=1;i<=N;i++)      {          int t=findRoot(i);          power[t]++;      }      sort(power+1,power+1+N,comp);            printf("%d",power[1]);      for(int i=2;i<=cou;i++)      {          printf(" %d",power[i]);      }        return 0;  }  


原创粉丝点击