PAT甲级——1114 Family Property (并查集)
此文章同步发布在我的CSDN上https://blog.csdn.net/weixin_44385565/article/details/89930332
1114 Family Property (25 分)
This time, you are supposed to help us collect the data for family-owned property. Given each person's family members, and the estate(房产)info under his/her own name, we need to know the size of each family, and the average area and number of sets of their real estate.
Input Specification:
Each input file contains one test case. For each case, the first line gives a positive integer N (≤). Then N lines follow, each gives the infomation of a person who owns estate in the format:
ID Father Mother k Child1⋯Childk Mestate Area
where ID is a unique 4-digit identification number for each person; Father and Mother are the ID's of this person's parents (if a parent has passed away, -1 will be given instead); k (0) is the number of children of this person; Childi's are the ID's of his/her children; Mestate is the total number of sets of the real estate under his/her name; and Area is the total area of his/her estate.
Output Specification:
For each case, first print in a line the number of families (all the people that are related directly or indirectly are considered in the same family). Then output the family info in the format:
ID M AVGsets AVGarea
where ID is the smallest ID in the family; M is the total number of family members; AVGsets is the average number of sets of their real estate; and AVGarea is the average area. The average numbers must be accurate up to 3 decimal places. The families must be given in descending order of their average areas, and in ascending order of the ID's if there is a tie.
Sample Input:
10
6666 5551 5552 1 7777 1 100
1234 5678 9012 1 0002 2 300
8888 -1 -1 0 1 1000
2468 0001 0004 1 2222 1 500
7777 6666 -1 0 2 300
3721 -1 -1 1 2333 2 150
9012 -1 -1 3 1236 1235 1234 1 100
1235 5678 9012 0 1 50
2222 1236 2468 2 6661 6662 1 300
2333 -1 3721 3 6661 6662 6663 1 100
Sample Output:
3
8888 1 1.000 1000.000
0001 15 0.600 100.000
5551 4 0.750 100.000
题目大意:根据给出的数据分类出各个家庭,然后输出家庭个数;接下来输出每个家庭的成员ID(只需输出家庭成员中最小的ID)、成员数量、平均房产数量、平均房产面积,输出顺序为平均房产面积降序、ID升序。
思路:用并查集S给家庭分类,为了方便找出最小的家庭成员ID,对并查集的操作稍作修改,集合元素初始化为对应的下标,若S[X]==X,则X为根,unionSet()函数将大根集合并到小根集合里;家庭成员计数时需要对已经访问过的ID进行标记,防止重复计数,用visit数组标记每个ID。
总结:其实我是比较害怕这类问题的,看起来简单,可是信息一多思考起来就容易混乱,需要很细心很耐心地分析,用不到什么算法知识却超级消耗时间~
#include <iostream>
#include <vector>
#include <unordered_map>
#include <algorithm>
using namespace std;
struct node1 {
int ID, fID, mID, k, Me, area;
vector <int> child;
};
struct node2 {
int sumM = , sumSets = , sumArea = ;
};
struct node3 {
int ID, M;
float AVGs, AVGa;
};
vector <int> S();
vector <bool> visit(, false);
void initialize();//对集合S进行初始化
bool cmp(node3 &a, node3 &b);//排序规则
int getNum(node1 &a);//获取家庭成员的数量
int find(int X);
void unionSet(int X, int Y);
int main()
{
int N;
scanf("%d", &N);
vector <node1> data(N);
unordered_map <int, node2> mp;
initialize();
for (int i = ; i < N; i++) {
node1 tmp;
scanf("%d%d%d%d", &tmp.ID, &tmp.fID, &tmp.mID, &tmp.k);
if (tmp.fID != -)
unionSet(tmp.ID, tmp.fID);
if (tmp.mID != -)
unionSet(tmp.ID, tmp.mID);
if (tmp.k != ) {
for (int j = ; j < tmp.k; j++) {
int cID;
scanf("%d", &cID);
tmp.child.push_back(cID);
unionSet(tmp.ID, cID);
}
}
scanf("%d%d", &tmp.Me, &tmp.area);
data[i] = tmp;
}
for (int i = ; i < N; i++) {
int ID = find(data[i].ID);
mp[ID].sumM += getNum(data[i]);
mp[ID].sumSets += data[i].Me;
mp[ID].sumArea += data[i].area;
}
vector <node3> ans;
for (auto it = mp.begin(); it != mp.end(); it++) {
int ID = it->first,
M = it->second.sumM;
float AVGs = it->second.sumSets*1.0 / M,
AVGa = it->second.sumArea*1.0 / M;
ans.push_back({ ID,M,AVGs,AVGa });
}
sort(ans.begin(), ans.end(), cmp);
printf("%d\n", ans.size());
for (int i = ; i < ans.size(); i++)
printf("%04d %d %.3f %.3f\n", ans[i].ID, ans[i].M, ans[i].AVGs, ans[i].AVGa);
return ;
}
int getNum(node1 &a) {
int n = ;
if (!visit[a.ID]) {
n++;
visit[a.ID] = true;
}
if ((a.fID != - )&& (!visit[a.fID])) {
n++;
visit[a.fID] = true;
}
if ((a.mID != -) && (!visit[a.mID])) {
n++;
visit[a.mID] = true;
}
if (a.k != ) {
for (int i = ; i < a.k; i++) {
if (!visit[a.child[i]]) {
n++;
visit[a.child[i]] = true;
}
}
}
return n;
}
void unionSet(int X, int Y) {
int rootX = find(X),
rootY = find(Y);
if (rootX > rootY)
S[rootX] = S[rootY];
else
S[rootY] = S[rootX];
}
int find(int X) {
if (S[X] == X) {
return X;
}
else {
return S[X] = find(S[X]);//递归地压缩路径
}
}
void initialize() {
for (int i = ; i < ; i++)
S[i] = i;//将集合元素初始化为对应的下标,每个集合的根节点就是当前家庭的最小ID
}
bool cmp(node3 &a, node3 &b) {
if (a.AVGa != b.AVGa)
return a.AVGa > b.AVGa;
else
return a.ID < b.ID;
}
PAT甲级——1114 Family Property (并查集)的更多相关文章
- PAT甲级1114. Family Property
PAT甲级1114. Family Property 题意: 这一次,你应该帮我们收集家族财产的数据.鉴于每个人的家庭成员和他/她自己的名字的房地产(房产)信息,我们需要知道每个家庭的规模,以及他们的 ...
- PAT 1114 Family Property[并查集][难]
1114 Family Property(25 分) This time, you are supposed to help us collect the data for family-owned ...
- PAT甲题题解-1107. Social Clusters (30)-PAT甲级真题(并查集)
题意:有n个人,每个人有k个爱好,如果两个人有某个爱好相同,他们就处于同一个集合.问总共有多少个集合,以及每个集合有多少人,并按从大到小输出. 很明显,采用并查集.vis[k]标记爱好k第一次出现的人 ...
- PAT 甲级 1021 Deepest Root (并查集,树的遍历)
1021. Deepest Root (25) 时间限制 1500 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue A graph ...
- PAT甲级——1107 Social Clusters (并查集)
本文同步发布在CSDN:https://blog.csdn.net/weixin_44385565/article/details/90409731 1107 Social Clusters (30 ...
- pat甲级1114
1114 Family Property(25 分) This time, you are supposed to help us collect the data for family-owned ...
- PAT甲级——A1114 Family Property【25】
This time, you are supposed to help us collect the data for family-owned property. Given each person ...
- PAT 1013 Battle Over Cities(并查集)
1013. Battle Over Cities (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue It ...
- PAT l2-010 排座位 【并查集】
L2-010. 排座位 时间限制 150 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 布置宴席最微妙的事情,就是给前来参宴的各位宾客安排座位. ...
随机推荐
- ActiveMQ之点对点使用
package com.toov5.producer; import javax.jms.Connection; import javax.jms.JMSException; import javax ...
- 如何用命令行删除EasyBCD开机选择项?
用硬盘安装Ubuntu方法的windows双系统电脑上面,很多人都是用EasyBCD设置的开机启动选择.所以当我们不需要双系统的时候,或者已经删除双系统后,或者安装双系统失败的情况下,发现电脑的开机启 ...
- 理解多线程中的ManualResetEvent(C#)
线程是程序中的控制流程的封装.你可能已经习惯于写单线程程序,也就是,程序在它们的代码中一次只在一条路中执行.如果你多弄几个线程的话,代码运行可能会更加“同步”.在一个有着多线程的典型进程中,零个或更多 ...
- Eclipse_配置_00_资源帖
1.Eclipse常用设置 2.eclipse设置和优化 3.Eclipse在工作中的一些常用设置及快捷键整理 4.Eclipse常用插件下载地址
- 安装.NET Core 3.0预览版后VS项目目标框架中不显示的解决方法
下载了微软在GitHub上的cSharpSamples项目后发现其中一些项目使用框架为.NET Core3.0,就下载了.NET Core3.0,但发现项目依然不可用,编译时提示如下 当前 .net ...
- linux网络编程 gethostbyname()
gethostbyname()返回对应于给定主机名的包含主机名字和地址信息的hostent结构指针.结构的声明与gethostaddr()中一致. 返回对应于给定主机名的主机信息. #include ...
- fscanf和fgets用法
首先要对fscanf和fgets这两个文件函数的概念有深入的了解,对于字符串输入而言这两个函数有一个典型的区别是: fscanf读到空格或者回车时会把空格或回车转化为/(字符串结束符)而fgets函数 ...
- BZOJ3230 相似子串[后缀数组+二分+st表]
BZOJ3230 相似子串 给一个串,查询排名i和j的子串longest common suffix和longest common prefix 思路其实还是蛮好想的,就是码起来有点恶心.可以发现后缀 ...
- BZOJ3295:[CQOI2011]动态逆序对
浅谈树状数组与线段树:https://www.cnblogs.com/AKMer/p/9946944.html 题目传送门:https://www.lydsy.com/JudgeOnline/prob ...
- Vijos1221:神秘的配方
背景 每天中午的下课铃一响,浙江镇海中学的同学们都会冲出学校来附近的小饭馆吃饭,刹那间天昏地暗,飞砂走石,家家餐馆内都是一片黑压压的人 .馄饨店.饺子馆,在学校附近开一家红一家.身为镇海中学信息中心首 ...