PTA甲级考试真题练习114——1114 Family Property

题目

在这里插入图片描述

思路

并查集
在并查集的过程中进行set和area的累加,最终每一个根上就是总的家庭成员set和area,然后遍历father数组 ,如果发现跟则加入汇总数组,最后排序输出

代码

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int nmax = 1005;
const int inf = 2147483647;
int father[10010];
struct info {
	int sets, area;
}info_array[10010];
struct path {
	double avsets, avarea;
	int num, minID;
};
vector<path> v;
path p;
bool visited[10010];
bool cmp(const path& a, const path& b) {
	if (a.avarea != b.avarea)
		return a.avarea > b.avarea;
	else
		return a.minID < b.minID;
}

int find(int i) {
	int j = i;
	while (father[j] >= 0)  j = father[j];
	int t;
	for (int k = i; k != j; k = t) {
		t = father[k];
		father[k] = j;
	}
	return j;
}

void merge(int i, int j) {
	int root1 = find(i);
	int root2 = find(j);
	if (root1 != root2) {
		if (root1 < root2) {
			father[root1] += father[root2];
			father[root2] = root1;
			info_array[root1].sets += info_array[root2].sets;
			info_array[root1].area += info_array[root2].area;
		}
		else {
			father[root2] += father[root1];
			father[root1] = root2;
			info_array[root2].sets += info_array[root1].sets;
			info_array[root2].area += info_array[root1].area;
		}
	}
}

int main()
{
	int n;
	cin >> n;
	fill(father, father + 10010, inf);
	for (int i = 0; i < n; ++i) {
		int cur, pa1, pa2, childnum;
		cin >> cur >> pa1 >> pa2 >> childnum;
		vector<int> vec;
		if (!visited[cur]) {
			visited[cur] = 1;
			father[cur] = -1;
		}
		if (pa1 != -1) {
			vec.emplace_back(pa1);
		}
		if (pa2 != -1){
			vec.emplace_back(pa2);
		}
		for (int j = 0; j < childnum; ++j) {
			int tmp; cin >> tmp;
			vec.emplace_back(tmp);
		}
		int sets, area;
		cin >> sets >> area;
		int root = find(cur);
		info_array[root].sets += sets;
		info_array[root].area += area;
		for (auto& p : vec) {
			if (!visited[p]) {
				visited[p] = 1;
				father[p] = -1;
			}
			merge(cur, p);
		}
	}
	for (int i = 0; i < 10010; ++i) {
		if (father[i] < 0) {
			p.minID = i;
			p.num = -father[i];
			p.avarea = (double)info_array[i].area / p.num;
			p.avsets = (double)info_array[i].sets / p.num;
			v.emplace_back(p);
		}
	}
	sort(v.begin(), v.end(), cmp);
	cout << v.size() << endl;
	for (auto& p : v) {
		printf("%04d %d %.3lf %.3lf\n", p.minID, p.num, p.avsets, p.avarea);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值