PAT甲级 并查集 相关题_C++题解
并查集
PAT (Advanced Level) Practice 并查集 相关题
- 《算法笔记》 重点摘要
- 1034 Head of a Gang (30)
- 1107 Social Clusters (30)
- 1118 Birds in Forest (25)
《算法笔记》 9.6 并查集 重点摘要
1. 定义
father[i]表示元素 i的父结点father[i] = i表示元素 i 为该集合根结点- 每个集合只存在一个根结点,且其作为所属集合的标识
int father[N];
2. 初始化
最初每个元素都是一个独立的集合
for (int i = 0; i <= n; i++)
father[i] = i;
3. 查找
对给定结点寻找其根结点:反复寻找父结点直到根结点
- 递推实现
int findFather (int x){
while (x != father[x])
x = father[x];
return x;
}
- 递归实现
int findFather (int x){
if (x == father[x]) return x;
else return findFather(father[x]);
}
4. 合并
- 判断两元素是否在同一集合
- 分别查找两根结点
- 判断根结点是否相同
- 合并集合:其中一个根结点的父节点指向另一个根结点
- 性质:只对不同集合进行合并,保证同一个集合中不会产生环,即并查集每个集合都是一棵树
void Union (int a, int b){
int faA = findFather(a);
int faB = findFather(b);
if (faA != faB) father[faA] = faB;
}
5. 路径压缩
将当前结点查询路径上所有结点的父节点都指向根节点
- 递推实现
int findFather (int x){
int y = x; // 将初始查询结点记录下来
while (x != father[x]) // 用 x 进行回溯
x = father[x]; // 找到 x 对应根结点记录在 x 里
while (y != father[y]){ // 用记录的初始查询结点重新回溯
int z = y; //将此结点记录下来
y = father[y]; //向父结点回溯
father[z] = x; //将当前结点指向根结点
}
return x;
}
- 递归实现
int findFather (int x){
if (x == father[x]) return x;
else{
int F = findFather(father[x]);
father[x] = F;
return F;
}
}
1034 Head of a Gang (30)
题目思路
- 未作哈希函数,直接用
map<string,string>存储父子关系,用map<string,int>存储结点对应参数 - 输入时将通话时长记录在个人对应的权重 map 中
- 若此人未出现过 (
father.find(name1) == father.end()),将独立成一个新集合,将其加入 map 并进行初始化father[name1] = name1 - 若已经出现过,不必初始化,直接与另一个通话对象 Union 起来
- 在 Union 函数中,首先查找两个人对应的头目
- 每加入一个新人就会调用 Union 函数,也就会查找其头目
- 查找头目时,要保证头目是这个集合中权重最高的
- 那么每次找到其头目后,要比较头目与新人的权值,若新人权值大,应设置为新的头目
- 这样每次 Union 得到的都是两个人对应团伙中权值最大的头目,将权值更大的作为新的头目
- 边输入边处理于是输入完成后可找到每个人对应的头目,遍历一次将团伙总通话时长和总人数分别与头目对应存储起来
- 最后按标准筛选出符合要求的团伙,放到 map 中
- 先输出符合要求的团伙数量即对应 map.size() 再按要求输出团伙头目和团伙人数
#include<iostream>
#include<map>
using namespace std;
map<string,string> father;
map<string,int> weight, totaltime, membernum, head_num;
string findFather(string s){
string t = s;
while (father[s] != s) s = father[s];
if (weight[s] < weight[t]){
father[s] = t;
father[t] = t;
return t;
}
return s;
}
void Union(string s1, string s2){
string fa1 = findFather(s1);
string fa2 = findFather(s2);
if (weight[fa1] > weight[fa2]) father[fa2] = fa1;
else father[fa1] = fa2;
}
int main()
{
int n, k, time;
scanf("%d%d", &n, &k);
string name1, name2;
for (int i = 0; i < n; i++){
cin >> name1 >> name2 >> time;
weight[name1] += time;
weight[name2] += time;
if (father.find(name1) == father.end()) father[name1] = name1;
if (father.find(name2) == father.end()) father[name2] = name2;
Union(name1, name2);
}
for (auto it: father){
totaltime[findFather(it.first)] += weight[it.first];
membernum[findFather(it.first)]++;
}
for (auto it: membernum)
if (it.second > 2 && totaltime[it.first] / 2 > k) head_num[it.first] = it.second;
cout << head_num.size() << endl;
for (auto it: head_num) cout << it.first << " " << it.second << endl;
return 0;
}
简化前 findFather 函数
string findFather(string s){
while (father[s] != s){
string fa = father[s];
if (weight[fa] < weight[s]){
if (father[fa] == fa) father[s] = s;
else father[s] = father[fa];
father[fa] = s;
}
else s = father[s];
}
return s;
}
1107 Social Clusters (30)
题目思路
- 用 set 数组保存每个人的兴趣爱好
- 输入完成后遍历 set 数组,将每个与之前的人的爱好 set 有重合的进行合并
- 合并处理完成后,遍历 father 数组,记录根结点即集合数,给每个结点对应根结点记录的集合人数 ++
- 将 map 按值排序,成对放入 vector,写 cmp 函数实现,最后按要求输出
- 注意:合并时,要对此人之前所有人的兴趣集合进行检查,不能检查到有相同的就停下,有三个点过不去。
问题在于如果前面有一个人兴趣为{3},一个人兴趣为{5},现在这个人兴趣为{3,5},在处理这个人之前,前两个人并不会被放入同一个 cluster 中,只有将现在这个人与前两个人分别合并,他们三人才能进入同一个 cluster
#include<iostream>
#include<set>
#include<algorithm>
#include<vector>
#include<unordered_map>
using namespace std;
int father[1001];
set<int> hobbies[1001];
bool cmp (pair<int,int> a, pair<int,int> b){ return a.second > b.second; }
int findFather(int x){
while (x != father[x]) x = father[x];
return x;
}
void Union(int a, int b){
int faA = findFather(a);
int faB = findFather(b);
if (faA != faB) father[faA] = faB;
}
int main()
{
for (int i = 0; i < 1001; i++) father[i] = i;
int n, k, hobby, clusternum = 0;
scanf("%d", &n);
for (int i = 0; i < n; i++){
scanf("%d: ", &k);
for (int j = 0; j < k; j++){
scanf("%d", &hobby);
hobbies[i].insert(hobby);
}
}
for (int i = 1; i < n; i++)
for (int j = 0; j < i; j++)
for (auto it: hobbies[i])
if (hobbies[j].find(it) != hobbies[j].end()) Union(i,j);
unordered_map<int,int> peoplenum;
for (int i = 0; i < n; i++){
if (father[i] == i) clusternum++;
peoplenum[findFather(i)]++;
}
vector<pair<int,int>> sortnum;
for (auto it: peoplenum) sortnum.push_back({it.first,it.second});
sort(sortnum.begin(),sortnum.end(),cmp);
printf("%d\n%d",clusternum,sortnum[0].second);
for (int i = 1; i < sortnum.size(); i++) printf(" %d",sortnum[i].second);
return 0;
}
1118 Birds in Forest (25)
题目思路
- 鸟编号从 1 开始,father 数组大小要开到 10001,并查集初始化
father[i] = i - 每输入一幅画中鸟的数量,先接收输入第一只鸟的编号,再循环接收其他的鸟,将后输入的鸟与第一只鸟合并
- 用 set 记录鸟的数量,每输入一只鸟就压入 set,set 会自动去重,输入完成后 set 的大小即为鸟的数量
- 由于鸟编号连续,由 set 大小即可知 father 数组记录到了哪里
- 遍历记录了鸟信息的部分 father 数组,找到
father[i+1] == i+1的即为根节点,根结点树即为集合数也即为树的棵数 - 最后看两只鸟是否在同一棵树,分别查询两只鸟的根结点,比较是否相等即可
#include<iostream>
#include<set>
using namespace std;
int father[10001];
int findFather(int x){
while (x != father[x]) x = father[x];
return x;
}
void Union(int a, int b){
int faA = findFather(a);
int faB = findFather(b);
if (faA != faB) father[faA] = faB;
}
int main()
{
for (int i = 0; i < 10001; i++) father[i] = i;
int n, k, q, q1, q2, fbird, bird, treenum = 0;
scanf("%d", &n);
set<int> birds;
for (int i = 0; i < n; i++){
scanf("%d%d", &k, &fbird);
birds.insert(fbird);
for (int j = 0; j < k - 1; j++){
scanf("%d", &bird);
birds.insert(bird);
Union(fbird,bird);
}
}
for (int i = 0; i < birds.size(); i++)
if (father[i+1] == i+1) treenum++;
printf("%d %d\n", treenum, birds.size());
scanf("%d", &q);
for (int i = 0; i < q; i++){
scanf("%d%d", &q1, &q2);
printf("%s\n", findFather(q1) == findFather(q2) ? "Yes" : "No");
}
return 0;
}
PAT甲级 并查集 相关题_C++题解的更多相关文章
- PAT甲级 图的遍历 相关题_C++题解
图的遍历 PAT (Advanced Level) Practice 图的遍历 相关题 目录 <算法笔记>重点摘要 1021 Deepest Root (25) 1076 Forwards ...
- PAT甲级 Dijkstra 相关题_C++题解
Dijkstra PAT (Advanced Level) Practice Dijkstra 相关题 目录 <算法笔记>重点摘要 1003 Emergency (25) <算法笔记 ...
- PAT甲级 二叉树 相关题_C++题解
二叉树 PAT (Advanced Level) Practice 二叉树 相关题 目录 <算法笔记> 重点摘要 1020 Tree Traversals (25) 1086 Tree T ...
- PAT甲级 二叉查找树 相关题_C++题解
二叉查找树 PAT (Advanced Level) Practice 二叉查找树 相关题 目录 <算法笔记> 重点摘要 1099 Build A Binary Search Tree ( ...
- PAT甲级 图 相关题_C++题解
图 PAT (Advanced Level) Practice 用到图的存储方式,但没有用到图的算法的题目 目录 1122 Hamiltonian Cycle (25) 1126 Eulerian P ...
- PAT甲级 树 相关题_C++题解
树 目录 <算法笔记>重点摘要 1004 Counting Leaves (30) 1053 Path of Equal Weight (30) 1079 Total Sales of S ...
- PAT甲级 堆 相关题_C++题解
堆 目录 <算法笔记>重点摘要 1147 Heaps (30) 1155 Heap Paths (30) <算法笔记> 9.7 堆 重点摘要 1. 定义 堆是完全二叉树,树中每 ...
- PAT题解-1118. Birds in Forest (25)-(并查集模板题)
如题... #include <iostream> #include <cstdio> #include <algorithm> #include <stri ...
- 【HDU1231】How Many Tables(并查集基础题)
什么也不用说,并查集裸题,直接盲敲即可. #include <iostream> #include <cstring> #include <cstdlib> #in ...
随机推荐
- python pillow 绘制图片
demo1 #coding=utf- from PIL import Image img = Image.,))###创建一个5*5的图片 pixTuple = (,,,)###三个参数依次为R,G, ...
- docker搭建hadoop HA出错问题总结记录。
错误1: ssh连接云主机: ssh root@39.106.xx.xx 报错:THE AUTHENTICITY OF HOST XX CAN’T BE ESTABLISHED 解决办法: ssh - ...
- known_hosts有什么用?
一.问题描述 当我连接我的服务器的时候,返回信息如下 二.问题分析 返回的信息是什么意思? IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY! ...
- 对请求数据的格式化 方案 Spring Cloud Gateway features:
对请求数据的格式化 例如 {body:{}}--->{data:{}} 执行阶段概念 · OpenResty最佳实践 · 看云 https://www.kancloud.cn/kancloud/ ...
- paint之文字示例
package com.loaderman.customviewdemo; import android.content.Context; import android.graphics.Canvas ...
- IO流概述
作用: 处理设备之间的数据传输的 I: Input(输入) , O: Output(输出) 什么是输入和输出? 我们说输入和输出问题是站在内存的角度而言 , 如果我们程序读取硬盘上的数据那么就是输入 ...
- Python中的logging模块就这么用
Python中的logging模块就这么用 1.日志日志一共分成5个等级,从低到高分别是:DEBUG INFO WARNING ERROR CRITICALDEBUG:详细的信息,通常只出现在诊断问题 ...
- Windows 操作系统 端口转发
在Windows 下可以使用netsh interface portproxy 命令实现端口转发功能. 例:netsh interface portproxy add v4tov4 listenpor ...
- RT-Thread代码启动过程——以及 $Sub$ $main 与 $Super$ $main
[转]https://blog.csdn.net/yang1111111112/article/details/80913001 我们找到系统复位的地方,可以往下单步跟踪. ①从系统初始化开始执行,将 ...
- 【Leetcode_easy】819. Most Common Word
problem 819. Most Common Word solution: class Solution { public: string mostCommonWord(string paragr ...