L2-007 家庭房产

文章描述了一种利用并查集数据结构解决家庭成员关系整合的问题。通过对输入数据的处理,构建二元组表示家庭成员关系,并使用并查集进行家庭合并。同时,文章还涉及到了如何存储和更新每个家庭的信息,以及最后对结果进行排序输出的过程。
摘要由CSDN通过智能技术生成

 输入:

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

解题思路:

首先我们要对输入的数据进行处理,这里我们是将所有有关系的两个人的编号全部存放到一个二元组中,对于处理出来的二元组,用并查集来进行维护,注意在用并查集进行合并的时候,要将编号大的合并到编号小的节点上,然后将大编号节点上的信息加到小结点上,这样就完成了同一个家庭的合并和信息的更新,然后我们就要遍历所有可能出现过的编号,因此我们要将所有出现过的编号开一个数组额外标记一下,这里的标记主要在两个地方,一个是对二元组里的两个编号分别标记,另一种情况是如果这个家庭中只有一个人,那么这个人在二元组中就不会出现,所以要在输入的时候就要进行标记。

最后将我们需要输出的信息弄成一个结构体,将这些结构体放到一个vector中,然后按照题目要求进行排序,最后输出结果即可。

#include <bitsdc++.h>
using namespace std;
const int N=1e5+10;
int p[N],peo[N],n,idx,tao[N],s[N];
pair<int,int>e[100010];
bool st[N];
struct node{
	int bian;
	int num;
	int tao;
	int sq;
};
bool cmp(node a,node b)
{
	if((double)a.sq/a.num!=(double)b.sq/b.num)
	return (double)a.sq/a.num>(double)b.sq/b.num;
	else
	return a.bian<b.bian;
}
int find(int x)
{
	if(x!=p[x])
	p[x]=find(p[x]);
	return p[x];
}
void merge(int x,int y)
{
	int fx=find(x);
	int fy=find(y);
	if(fx!=fy)
	{
		int minv=min(fx,fy),maxv=max(fx,fy);
		p[maxv]=minv;
		peo[minv]+=peo[maxv];
		tao[minv]+=tao[maxv];
		s[minv]+=s[maxv];
	}
}
int main()
{
	for(int i=0;i<N;i++)
	{
		p[i]=i;
		peo[i]=1;
	}
	cin>>n;
	int id,fa,ma,k;
	for(int i=1;i<=n;i++)
	{
		cin>>id>>fa>>ma>>k;
		if(fa!=-1)
		e[++idx]={id,fa};
		if(ma!=-1)
		e[++idx]={id,ma};
		st[id]=true;//有可能这个家庭只有这个人自己 
		for(int j=1;j<=k;j++)
		{
			int x;
			cin>>x;
			e[++idx]={id,x};
		}
		cin>>tao[id]>>s[id];
	}
	for(int i=1;i<=idx;i++)
	{
		merge(e[i].first,e[i].second);
		st[e[i].first]=1;
		st[e[i].second]=1;
	}
	vector<node>ans;
	for(int i=0;i<N;i++)
	if(st[i]&&(p[i]==i))
	ans.push_back({i,peo[i],tao[i],s[i]});
	sort(ans.begin(),ans.end(),cmp);
	cout<<ans.size()<<endl;
	for(int i=0;i<ans.size();i++)
	printf("%04d %d %.3lf %.3lf\n",ans[i].bian,ans[i].num,(double)ans[i].tao/ans[i].num,(double)ans[i].sq/ans[i].num);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值