• [PAT] A1107 Social Clusters


    并查集

    AC代码

    #define _CRT_SECURE_NO_WARNINGS
    #include<iostream>
    #include <cstdio>
    #include <vector>
    #include<algorithm>
    using namespace std;
    #define N 1002
    int isRoot[N] = { 0 }, father[N];
    vector<int>hobbies[N];
    int findFather(int v) {
    	int a = v;
    	while (father[v] != v)v = father[v];
    	while (father[a] != v) {
    		int z = father[a];
    		father[a] = v;
    		a = z;
    	}
    	return v;
    }
    void merge(int a, int b) {
    	int u = findFather(a);
    	int v = findFather(b);
    	if (u != v)father[u] = v;
    }
    bool ifmerge(int a, int b) {
    	int flag = false;
    	for (int i = 0;i < hobbies[a].size();i++)
    		for (int j = 0;j < hobbies[b].size();j++) {
    			if (hobbies[a][i] == hobbies[b][j])flag = true;
    		}
    	return flag;
    }
    bool cmp(int a, int b) {
    	return a > b;
    }
    int main() { 
    	int n, i, j;    
    	scanf("%d", &n); 
    	int thobby, numhobby;
    	for (i = 1;i <= n;i++) {
    		scanf("%d: ", &numhobby);
    		for (j = 0;j < numhobby;j++) {
    			scanf("%d", &thobby);
    			hobbies[i].push_back(thobby);
    		}
    	}
    	for (i = 1;i <= n;i++)
    		father[i] = i;
    	for (i = 1;i < n;i++) {
    		for (j = i + 1;j <= n;j++) {
    			if(ifmerge(i, j))
    				merge(i, j);
    		}
    	}
    	for (i = 1;i <= n;i++)
    		isRoot[findFather(i)]++;
    	int numcluster = 0;
    	for (i = 1;i <= n;i++)
    		if (isRoot[i] != 0)numcluster++;
    	printf("%d
    ", numcluster);
    	sort(isRoot, isRoot + n + 1, cmp);
    	if (isRoot[0] != 0)printf("%d", isRoot[0]);
    	i = 1;
    	while (isRoot[i] != 0) {
    		printf(" %d", isRoot[i]);
    		i++;
    	}
    	return 0; 
    }
    
    

    对比柳神的代码,发现爱好不需要用vector数组存起来,可以输入一个处理一个。即:

    用course[t]表示任意一个喜欢t活动的人的编号。

    1. 如果当前的活动t之前没有人喜欢过(course[t]==0),那么就course[t] = i,i为它自己的编号,表示i为喜欢course[t]的一个人的编号。
    2. 如果t之前有人喜欢过了,那么就让i和喜欢这个活动的人(即course[t])处在同一个社交圈里, 即Union(i, findFather(course[t]))。

    代码实现如下:

    for(int i = 1; i <= n; i++) {
        scanf("%d:", &k);
        for(int j = 0; j < k; j++) {
            scanf("%d", &t);
            if(course[t] == 0)
                course[t] = i;
            else Union(i, course[t]);
        }
    }
    
  • 相关阅读:
    500 多个 Linux 命令文档搜索
    C++ 字符串基本操作
    串的模式匹配算法
    查看、启动、关闭防火墙
    天润融通面试
    LeetCode 169. 求众数
    【面试题】人人车一次面试总结
    一个完整的 JS 身份证校验代码
    oracle多表查询
    百度地图的Icon
  • 原文地址:https://www.cnblogs.com/yue36/p/13322119.html
Copyright © 2020-2023  润新知