团体程序设计天梯赛 L2-007 家庭房产(并查集模拟)

L2-007 家庭房产

分数 25

给定每个人的家庭成员和其自己名下的房产,请你统计出每个家庭的人口数、人均房产面积及房产套数。

输入格式:

输入第一行给出一个正整数N(≤1000),随后N行,每行按下列格式给出一个人的房产:

编号 父 母 k 孩子1 ... 孩子k 房产套数 总面积

其中编号是每个人独有的一个4位数的编号;分别是该编号对应的这个人的父母的编号(如果已经过世,则显示-1);k(0≤k≤5)是该人的子女的个数;孩子i是其子女的编号。

输出格式:

首先在第一行输出家庭个数(所有有亲属关系的人都属于同一个家庭)。随后按下列格式输出每个家庭的信息:

家庭成员的最小编号 家庭人口数 人均房产套数 人均房产面积

其中人均值要求保留小数点后3位。家庭信息首先按人均面积降序输出,若有并列,则按成员编号的升序输出。

输入样例:

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

输出样例:

3
8888 1 1.000 1000.000
0001 15 0.600 100.000
5551 4 0.750 100.000

题解

根据题意进行模拟,然后用并查集归类他们的家庭,在结构体里面写一个判断函数,用来最后输出的时候判断。写起来好复杂的感觉 

#include<bits/stdc++.h>
using namespace std;
int n;
struct node{
	double fc=0.0;
	double mj=0.0;
	int minid=10000;
	int sum=0;
	int num;
	double rjfc;
	double rjmj;
    //用来后面判断输出的
	bool operator<(const node& other) const {
		if(rjmj==other.rjmj)
		{
			return minid>other.minid;
		}
		return rjmj<other.rjmj;
	}
}s[10005];

int v[10005];//是否有这个编号
map<int,int> f;//并查集
map<int,vector<node> > fl;//家庭
priority_queue<node> q;//输出顺序用优先队列储存
//并查集
int find(int x)
{
	if(f[x]==x)
	{
		return x;
	}
	f[x]=find(f[x]);
	return f[x];
}
//合并
void hb(int x,int y)
{
	if(x==-1 || y==-1) return;
	int u=find(x),v=find(y);
	if(u!=v)
	{
		f[v]=u;
	}
}
int main()
{
	cin>>n;
    //初始化
	for(int i=0;i<=10000;i++)
	{
		f[i]=i;
	}
	while(n--)
	{
		int num,fu,mu,k;
		cin>>num>>fu>>mu>>k;
		v[num]=1;
		hb(num,fu);
		hb(num,mu);
		if(fu!=-1)
		{
			v[fu]=1;
		}
		if(mu!=-1)
		{
			v[mu]=1;
		}
		while(k--)
		{
			int x;
			
			cin>>x;
			v[x]=1;
			hb(num,x);
		}
		int fc,mj;
		
		cin>>s[num].fc>>s[num].mj;
	}
	for(auto k:f)
	{
		if(v[k.first]==1)//如果有这个人
		{
            //每次更新最小的成员
			s[find(k.second)].minid=min(s[find(k.second)].minid,k.first);
		
			s[find(k.second)].sum++;
			if(find(k.second)!=k.first)
			{
				s[find(k.second)].fc+=s[k.first].fc;
				s[find(k.second)].mj+=s[k.first].mj;
			}
			
			fl[find(k.second)].push_back(s[k.first]);
			//cout<<find(k.second)<<" "<<k.first<<endl;
		 } 
		
	}
	cout<<fl.size()<<endl;
	
	for(auto k:fl)
	{
		s[k.first].rjfc=s[k.first].fc/s[k.first].sum;
		s[k.first].rjmj=s[k.first].mj/s[k.first].sum;
		q.push(s[k.first]);
	
		
	}
	while(!q.empty())
	{
		printf("%04d ",q.top().minid);
		cout<<q.top().sum<<" ";
		cout<<fixed<<setprecision(3)<<q.top().rjfc<<" ";
		cout<<fixed<<setprecision(3)<<q.top().rjmj<<endl;
		q.pop();
	}
	return 0;
}

  • 20
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值