1107 Social Clusters (考察并查集)
大致题意就是给出 N个人的兴趣爱好,如果A与B有相同的爱好H1,那么A与B是朋友,如果B与C有相同的爱好H2,那么B与C是朋友,进一步有A与C是朋友。
输入样例分析:
8 //表示有8个人
3: 2 7 10 //表示人物 1有3个爱好,分别是2 7 10
1: 4 //表示人物 2有1个爱好,分别是4
2: 5 3
1: 4
1: 3
1: 4
4: 6 8 1 5
1: 4
整理成格式
爱好:人物,人物,...
1: 7
2: 1
3: 3 5
4: 2 4 6 8
5: 3 7
6: 7
7: 1
8: 7
10: 1
我们可以发现
爱好3包含人物3、人物5,爱好5包含人物3、人物7,所以3 5 7是一个朋友圈。
爱好4包含人物2、人物4、人物6、人物8,所以2 4 6 8是一个朋友圈。
最后, 1 是一个朋友圈。
所以一共有三个朋友圈。
1 #include<iostream> 2 #include<vector> 3 #include<map> 4 #include<algorithm> 5 using namespace std; 6 const int maxn = 2000; 7 map<int,vector<int> > mp; 8 int father[maxn]; 9 int isRoot[maxn] = {0}; 10 //第一步,初始化所有集合 11 void init(int n) { 12 for(int i = 1; i <= n; ++i) 13 father[i] = i; 14 } 15 //第二步,查找根结点 16 int findFather(int a) { 17 int b = a; 18 while(a != father[a])//找到根结点 19 a = father[a]; 20 while(b != father[b]) {//查找根结点时,路径上的所有结点指向根结点 21 int t = b; 22 b = father[b]; 23 father[t] = a; 24 } 25 return a; 26 } 27 28 //第三步,合并a,b所在的集合 29 void Union(int a,int b) { 30 int fa = findFather(a); 31 int fb = findFather(b); 32 if(fa != fb) 33 father[fa] = fb; 34 } 35 bool cmp(int a,int b) { 36 return a > b; 37 } 38 int main() { 39 int n; 40 scanf("%d",&n); 41 for(int i = 1; i <= n; ++i) { 42 int k,h; 43 scanf("%d:",&k); 44 for(int j = 0; j < k; ++j) { 45 scanf("%d",&h); 46 mp[h].push_back(i); 47 } 48 } 49 init(n); 50 for(auto it = mp.begin(); it != mp.end(); ++it) { 51 if(it->second.size() > 1) { 52 for(int i = 1 ; i < it->second.size(); ++i) { 53 Union(it->second[0],it->second[i]); 54 } 55 } 56 } 57 int cnt = 0; 58 for(int i = 1; i <= n ; ++i) { 59 int f = findFather(i); 60 if(isRoot[f] == 0) cnt++; 61 isRoot[f]++; 62 } 63 printf("%d\n",cnt); 64 sort(isRoot+1,isRoot+1+n,cmp); 65 for(int i = 1; i <= cnt; ++i) { 66 if( i > 1) printf(" "); 67 printf("%d",isRoot[i]); 68 } 69 return 0; 70 }