A1114 Family Property (25分)

一、技术总结

  1. 这题考查内容为并查集,核心是用一个数组存储当前结点的父节点编号,操作有初始化、查找、合并。
  2. 题意首先理解一下,题目意思是给出N行,然后每行中首先给出自己的ID号、然后是父亲ID、再是母亲ID,如果父亲跟母亲已经去世,该ID好给出为-1,然后再给数字num,代表给人的孩子数,后面跟上num个孩子的ID号,最后是这个人拥有房子的数量和总面积。最后要求是如果是有直接或间接关系的归为一个家庭,然后求出该家庭的平均房子数量,和平均面积都保留三位小数。输出结果按照平均面积降序输出,如果一样则按各自家庭中最小ID号升序输出。
  3. 首先应该定义一个father数组用于并查集操作,同时设置一个visit数组用于存储所有有效结点。在其实在读取每行的时候就可以进行合并操作,这里有一点需要注意一下,因为题目要求是给出每个家庭成员中的最小ID号来代表该家庭,所以合并时,应该直接将ID号较小的作为父节点。
  4. 我们设置Data结构体用于存储每行的数据,用这是node结构体用于存储将要输出的家庭,里面包含ID号、家庭人数、平均房子数量、平均住房面积、还有标志位flag用于查看该ID号是否为有效家庭,即用于统计家庭数量。通过遍历data中的每行,最小家庭号直接用查找函数查找有其父节点,同时也加上该成员的住房面积和房子数量。而成员数量通过之前的visit数组遍历,有效结点分别归属于哪一个家庭。这时统计cnt也就是家庭数量。
  5. 最后统计完成后,计算出平均住房面积、数量,再使用sort函数排序,最后输出结果。

二、参考代码

#include<bits/stdc++.h>
using namespace std;
const int MAXV = 1010;
const int MAXN = 10000;
struct Data{
	int id, fid, mid;
	int num, area;
	int kid[10];
}data[MAXV];
struct node{
	int id, people;
	double num, area;
	bool flag = false;
}ans[MAXN];
bool visit[MAXN];
int father[MAXN];
int findFather(int x){
	int a = x;
	while(x != father[x]){
		x = father[x];
	}
	while(a != father[a]){
		int z = a; 
		a = father[a];
		father[z] = x;
	}
	return x;
}
void Union(int a, int b){
	int faA = findFather(a);
	int faB = findFather(b);
	if(faA > faB){
		father[faA] = faB;
	}else if(faA < faB){
		father[faB] = faA;
	}
}
bool cmp(node a, node b){
	if(a.area != b.area){
		return a.area > b.area;
	}else{
		return a.id < b.id;
	}
}
int main(){
	int n, k, cnt = 0;
	scanf("%d", &n);
	for(int i = 0; i < 10000; i++){
		father[i] = i;
	}
	for(int i = 0; i < n; i++){
		scanf("%d %d %d %d", &data[i].id, &data[i].fid, &data[i].mid, &k);
		visit[data[i].id] = true;
		if(data[i].fid != -1){
			visit[data[i].fid] = true;
			Union(data[i].id, data[i].fid);
		}
		if(data[i].mid != -1){
			visit[data[i].mid] = true;
			Union(data[i].id, data[i].mid);
		}
		for(int j = 0; j < k; j++){
			scanf("%d", &data[i].kid[j]);
			visit[data[i].kid[j]] = true;
			Union(data[i].id, data[i].kid[j]);
		}
		scanf("%d %d", &data[i].num, &data[i].area);
	}
	for(int i = 0; i < n; i++){
		int id = findFather(data[i].id);
		ans[id].id = id;
		ans[id].num += data[i].num;
		ans[id].area += data[i].area;
		ans[id].flag = true;
	}
	for(int i = 0; i < MAXN; i++){
		if(visit[i]){
			int id = findFather(i);
			ans[id].people++;
		}
		if(ans[i].flag){
			cnt++;
		}
	}
	for(int i = 0; i < MAXN; i++){
		if(ans[i].flag){
			ans[i].num = (double)(ans[i].num * 1.0 / ans[i].people);
			ans[i].area = (double)(ans[i].area * 1.0 / ans[i].people);
		}
	}
	sort(ans, ans+MAXN, cmp);
	printf("%d
", cnt);
	for(int i = 0; i < cnt; i++){
		printf("%04d %d %.3f %.3f
", ans[i].id, ans[i].people, ans[i].num, ans[i].area);
	} 
	return 0;
}
作者:睿晞
身处这个阶段的时候,一定要好好珍惜,这是我们唯一能做的,求学,钻研,为人,处事,交友……无一不是如此。
劝君莫惜金缕衣,劝君惜取少年时。花开堪折直须折,莫待无花空折枝。
曾有一个业界大牛说过这样一段话,送给大家:   “华人在计算机视觉领域的研究水平越来越高,这是非常振奋人心的事。我们中国错过了工业革命,错过了电气革命,信息革命也只是跟随状态。但人工智能的革命,我们跟世界上的领先国家是并肩往前跑的。能身处这个时代浪潮之中,做一番伟大的事业,经常激动的夜不能寐。”
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
原文地址:https://www.cnblogs.com/tsruixi/p/12989314.html