1114. Family Property 解析

并查集的考察。

再合并的时候需要注意让最小的ID当作父亲结点,便于后面的输出。

#include <iostream>
#include <vector>
#include <set>
#include <algorithm>

#define MAX 10000

using namespace std;

struct person{
	int ID;
	float m_estate;
	float aera;
	float sum;
	person() { m_estate = 0; aera = 0; sum = 1; }
};


person p[MAX];
vector <person> family;//最终结果
set <int> s;//用来统计有资产的id
set <int> f;//用来统计家庭
int n,n_child;

void InitSet() {
	for (int i = 0; i < MAX; i++) {
		p[i].ID = i;
	}
}

void CompressSet(int top ,int x) {
	if (p[x].ID != top) {
		CompressSet(top, p[x].ID);
		p[x].ID = top;
	}
}

int FindSet(int x) {
	if (p[x].ID != x) {
		int top = FindSet(p[x].ID);
		CompressSet(top, x);
	}
	return p[x].ID;
}

void UnionSet(int x ,int y) {
	int a = FindSet(x);
	int b = FindSet(y);
	
	if (a < b) {
		p[b].ID = a;
		p[a].sum += p[b].sum;//不要弄反了
	}

	else if(a > b) {
		p[a].ID = b;
		p[b].sum += p[a].sum;//不要弄反了
	}
}


bool cmp(person p1, person p2) {
	if (p1.aera > p2.aera)
		return true;
	else if (p1.aera == p2.aera && p1.ID < p2.ID)
		return true;
	return false;
}

int main() {
	cin >> n;

	InitSet();

	int id, id_dad, id_mom, id_child;

	for (int i = 0; i < n; i++) {
		scanf("%d%d%d%d", &id, &id_dad, &id_mom, &n_child);
		s.insert(id);
		if(id_dad != -1)//父亲在
			UnionSet(id, id_dad);
		if(id_mom != -1)//母亲在
			UnionSet(id, id_mom);
		for (int j = 0; j < n_child; j++) {
			scanf("%d", &id_child);
			UnionSet(id, id_child);
		}
		scanf("%f%f", &p[id].m_estate, &p[id].aera);
	}

	set<int>::iterator it;

	//累加结果
	for (it = s.begin(); it != s.end(); it++) {
		id = FindSet(*it);
		if (id != *it) { //自己本身不累加
			p[id].aera += p[*it].aera;
			p[id].m_estate += p[*it].m_estate;
		}
		f.insert(id);
	}

	//统计家庭并计算
	for (it = f.begin(); it != f.end(); it++) {
		p[*it].aera /= p[*it].sum;
		p[*it].m_estate /= p[*it].sum;
		family.push_back(p[*it]);
	}

	sort(family.begin(), family.end(), cmp);

	cout << family.size() << endl;
	for (int i = 0; i < family.size(); i++) {
		printf("%04d %.0f %.03f %.03f\n", family[i].ID, family[i].sum, family[i].m_estate, family[i].aera);
	}



	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值