• PAT Advanced 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

    题目分析

    n个人,每个人都有自己喜欢的活动,有共同喜欢的活动的人组成集群,求集群数和每个集群中的组员个数

    解题思路

    辅助数组

    用int act[n]数组记录各活动任意一个喜欢的人,在并查集之外的辅助数组,某个活动第一次被喜欢时,将喜欢此活动的人作为其元素值

    并查集的使用

    输入编号为i的A喜欢的活动时,寻找此活动的任意喜欢的人act[i](设其为B),将A、B合并到一个集群

    统计操作

    统计根节点总数即为集群总数,并在此过程中记录每个集群中的组员数

    Code

    #include <iostream>
    #include <vector>
    #include <set>
    #include <algorithm>
    using namespace std;
    const int maxn=1010;
    int father[maxn],act[maxn],clst[maxn];
    /* 并查集 - 初始化*/
    void init(int n) {
    	for(int i=1; i<=n; i++) {
    		father[i]=i;
    	}
    }
    /* 并查集-查 */
    int find(int x) {
    	int a=x;
    	while(x!=father[x])
    		x=father[x];
    	while(a!=father[a]) {
    		int temp=father[a];
    		father[a]=x;
    		a=temp;
    	}
    	return x;
    }
    /* 并查集-并 */
    void Union(int a, int b) {
    	int af=find(a);
    	int bf=find(b);
    	if(af!=bf)
    		father[af]=bf;
    }
    bool cmp(int a, int b){
    	return a>b;
    }
    int main(int argc,char * argv[]) {
    	int n,t,h;
    	scanf("%d",&n);
    	init(n);
    	for(int i=1; i<=n; i++) {
    		scanf("%d:", &t);
    		for(int j=0; j<t; j++) {
    			scanf("%d", &h);
    			if(act[h]==0){
    				act[h]=i; //h习惯 第一次有人拥有 
    			}
    			Union(i, act[h]); //将i合并到所属集群中 
    		}
    	}
    	
    	// 统计集群数,及集群中成员个数 
    	set<int> cids;
    	for(int i=1;i<=n;i++){
    		clst[find(i)]++;
    		cids.insert(father[i]);
    	}
    	int ans=cids.size();
    	printf("%d
    ",ans);
    	sort(clst+1,clst+n+1, cmp); //从大到小 
    	for(int i=1;i<=ans;i++){
    		printf("%d",clst[i]);
    		if(i<ans)printf(" ");
    	}
    	return 0;
    }
    



  • 相关阅读:
    【递推】【概率】Gym
    【坐标变换】【二维偏序】【线段树】Gym
    【DLX算法】hdu3498 whosyourdaddy
    【DLX算法】poj2676 Sudoku
    【Pollard-rho算法】【DFS】poj2429 GCD & LCM Inverse
    Pollard-rho算法:模板
    【筛法求素数】【推导】【组合数】UVALive
    【二项式定理】【DFS】UVALive
    【并查集】【枚举倍数】UVALive
    【Floyd算法】Gym
  • 原文地址:https://www.cnblogs.com/houzm/p/12589861.html
Copyright © 2020-2023  润新知