1107. Social Clusters (30)[并查集]

2023-12-02 15:58
文章标签 30 查集 social clusters 1107

本文主要是介绍1107. Social Clusters (30)[并查集],希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. 原题: https://www.patest.cn/contests/pat-a-practise/1107

2. 思路:

题意:
根据共同的兴趣找出共有几个圈子。
思路:
并查集问题。
根据题意,很容易知道是关于集合的问题。对于集合问题,并查集是最简单的。
当然可以用bfs,但是没有并查集算法简捷。


并查集其实就两个函数,一个合并,一个查找根。
两个数组s和hobby。
初始时s[i]= -1, 表示每个人都是根。(根时,值的绝对值表示该集合人数)。
对于爱好,初始时,hobby[i] = 0,即无人有该爱好。
读入数据,对于k号的j个爱好,若该爱好i无人,那么hobby[i] = k,即k号有爱好i。
若该爱好i已经有人了(hobby[i] != 0), 那么说明这两个人可以是一个圈子,进行合并就好了。
所以,当读完数据时,集合也合并好了。


此时,我们要知道每个集合的根值是负值,非负则不是根。
那么我们升序排序,越小说明圈子人越多。
最后输出负值的圈子。
已AC。

3. 源码:

#include<iostream>
#include<vector>
#include<algorithm>//使用sort函数
using namespace std;int N;//总人数
vector<int> s;//存储圈子的情况,s[i]表示编号i的人的父结点号。
vector<int> hobby(1001, 0);//下标为兴趣编号,值表示拥有该兴趣的人的编号。void Union(int root1, int root2);//并查集的合并两个集合, 参数是两个集合的根(某人的编号)。
int FindRoot(int x);//并查集的查找集合的根, 参数是人的编号int main(void)
{//freopen("in.txt", "r", stdin);scanf("%d", &N);s.resize(N + 1, 0);//编号从1起for (int i = 1; i <= N; i++)//读入数据并进行处理合并{s[i] = -1;//并查集的初始化int num;//每个人的爱好数scanf("%d: ", &num);for (int j = 0; j < num; j++){int type;//爱好编号scanf("%d", &type);if (hobby[type] == 0)//第一次有人有该爱好,相当于该人可以作为集合的跟了,后面人都指向他。hobby[type] = i;else{int r1 = FindRoot(i);//找到i这个人的根int r2 = FindRoot(hobby[type]);//找到有这个爱好的人所在圈子的根Union(r1, r2);//合并两个圈子}}}sort(s.begin(), s.end());//升序int cnt = 0;//记录圈子数for (int i = 0; i < s.size() && s[i] < 0; i++)cnt++;printf("%d\n", cnt);for (int i = 0; i < cnt; i++){if (i != 0)printf(" ");printf("%d", -s[i]);}printf("\n");return 0;
}void Union(int root1, int root2)//并查集的合并两个集合, 参数是两个集合的根(某人的编号)。
{if (root1 < root2)//这里进行了优化,即按秩归并(把小集合并到大集合里,可以减少树深度)。{s[root1] += s[root2];//更新合并后的集合人数s[root2] = root1;		//小集合根指向新集合的根}else{s[root2] += s[root1];s[root1] = root2;}
}int FindRoot(int x)//并查集的查找集合的根, 参数是人的编号
{if (s[x] < 0)//小于0,找到了根return x;else//递归查找,这里也进行了优化。即路径压缩,把该圈子所有人都指向根,减少树深度。return s[x] = FindRoot(s[x]);
}


这篇关于1107. Social Clusters (30)[并查集]的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/445931

相关文章

30常用 Maven 命令

Maven 是一个强大的项目管理和构建工具,它广泛用于 Java 项目的依赖管理、构建流程和插件集成。Maven 的命令行工具提供了大量的命令来帮助开发人员管理项目的生命周期、依赖和插件。以下是 常用 Maven 命令的使用场景及其详细解释。 1. mvn clean 使用场景:清理项目的生成目录,通常用于删除项目中自动生成的文件(如 target/ 目录)。共性规律:清理操作

poj 1182 并查集 食物链类

题意: 有n只动物,分别编号1....n。所有动物都属于A,B,C中的一种,已知A吃B,B吃C,C吃A。 按顺序给出下面两种共K条信息: 1. x 和 y 属于同一类。 2. x 吃 y 。 然而这些信息可能会出错,有可能有的信息和之前给出的信息矛盾,也有的信息可能给出的 x 和 y 不在n的范围内。 求k条信息中有多少条是不正确的。 解析: 对于每只动物,创建3个元素 i

2024网安周今日开幕,亚信安全亮相30城

2024年国家网络安全宣传周今天在广州拉开帷幕。今年网安周继续以“网络安全为人民,网络安全靠人民”为主题。2024年国家网络安全宣传周涵盖了1场开幕式、1场高峰论坛、5个重要活动、15场分论坛/座谈会/闭门会、6个主题日活动和网络安全“六进”活动。亚信安全出席2024年国家网络安全宣传周开幕式和主论坛,并将通过线下宣讲、创意科普、成果展示等多种形式,让广大民众看得懂、记得住安全知识,同时还

POJ1988带权并查集

M u v 将u所在的堆移动到v所在的堆的上面 C u 求u的下面有多少块 带权并查集 import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;import java.math.BigInteger;i

POJ1703带权并查集

D: u v  u与v在不同的集合 A: u v  查询u与v的关系 1)压缩路径过程        fu->root   0  1  u-fu 0                 0  1   1                 1  0 2)合并过程 fu->fv      u->fu   0 1   v->fv 0            1 0 1            0

c++习题30-求10000以内N的阶乘

目录 一,题目  二,思路 三,代码    一,题目  描述 求10000以内n的阶乘。 输入描述 只有一行输入,整数n(0≤n≤10000)。 输出描述 一行,即n!的值。 用例输入 1  4 用例输出 1  24   二,思路 n    n!           0    1 1    1*1=1 2    1*2=2 3    2*3=6 4

嵌入式面试经典30问:二

1. 嵌入式系统中,如何选择合适的微控制器或微处理器? 在嵌入式系统中选择合适的微控制器(MCU)或微处理器(MPU)时,需要考虑多个因素以确保所选组件能够满足项目的具体需求。以下是一些关键步骤和考虑因素: 1.1 确定项目需求 性能要求:根据项目的复杂度、处理速度和数据吞吐量等要求,确定所需的处理器性能。功耗:评估系统的功耗需求,选择低功耗的MCU或MPU以延长电池寿命或减少能源消耗。成本

并查集基础与简单扩展应用

并查集 基础题目路径压缩 扩展应用扩展题目1扩展题目2 并查集的结构是一棵树 并查集有两种功能,一种是判断两个元素是否在同一集合,第二种是合并两个集合 并查集的实现需要记录每个节点的父亲节点 判断两个元素是否在同一集合,即判断两个元素的祖宗节点是否是一个节点(祖宗代表整棵树的根节点) 合并两个集合,即将任意一个集合祖宗的爸爸改为另一个集合的祖宗 基础题目 一共有

nyoj99(并查集+欧拉路+dfs)

单词拼接 时间限制: 3000 ms  |  内存限制: 65535 KB 难度: 5 描述 给你一些单词,请你判断能否把它们首尾串起来串成一串。 前一个单词的结尾应该与下一个单词的道字母相同。 如 aloha dog arachnid gopher tiger rat   可以拼接成:aloha.arachnid.dog.gopher.rat.tiger 输入 第一行是一个整

nyoj42(并查集解决欧拉回路)

一笔画问题 时间限制: 3000 ms  |  内存限制: 65535 KB 难度: 4 描述 zyc从小就比较喜欢玩一些小游戏,其中就包括画一笔画,他想请你帮他写一个程序,判断一个图是否能够用一笔画下来。 规定,所有的边都只能画一次,不能重复画。   输入 第一行只有一个正整数N(N<=10)表示测试数据的组数。 每组测试数据的第一行有两个正整数P,Q(P<=1000,Q<