天梯赛L2-007 【家庭房产】 并查集

本文通过一个具体的编程题目,详细介绍了如何使用并查集算法来处理复杂的数据关系,并提供了完整的C++实现代码。文章涵盖了并查集的基本概念、初始化、查找、合并等操作,以及如何优化合并过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接~https://www.patest.cn/contests/gplt/L2-007

分析:emmmmm,初次看题觉得很恶心,神烦这种输入一大堆乱七八糟数据还要求输出浮点数的题TAT

这次的并查集比较高明,合并的时候采取以num更小的为头目,也就是说,合并过程会把尽可能小的作为头目。。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e4+10;

struct Node{
	int id;
	int cnt,area;
}node[maxn];

struct Node2{
	int id,num;
	double area,cnt;
	bool flag;
}res[maxn];

int father[maxn];
bool cmp(Node2 a, Node2 b){
	if(a.flag && b.flag)
		return a.id<b.id;
	return a.flag>b.flag;
}
bool cmp2(Node2 a, Node2 b){
	if(a.area == b.area){
		return a.id < b.id;
	}
	return a.area>b.area;
}
void init(){
	for(int i = 0; i<10000; i++){
		father[i] = i;
	}
}
int getF(int x){
	int a = x;
	while(x != father[x]){
		x = father[x];
	}
	while(father[a] != x){
		int tem = father[a];
		father[a] = x;
		a = tem;
	}
	return x;
}
void merge(int a, int b){
	int fa = getF(a);
	int fb = getF(b);
	if(fa < fb){
		father[fb] = fa;
	}
	else {
		father[fa] = fb;
	}
	
}
int main(){
	init(); //初始化不能漏 
	int n,id,m,f,child,k,cnt,area;
	cin>>n;
	for(int i = 0; i<n; i++){
		cin>>id>>m>>f;
		node[i].id = id;
		if(m != -1){
			merge(id, m);
		}
		if(f != -1){
			merge(id, f);
		}
		cin>>k;
		for(int j = 0; j<k; j++){
			cin>>child;
			merge(id, child);
		}
		cin>>cnt>>area;
		node[i].cnt=cnt;
		node[i].area = area;
	}
	for(int i = 0; i<n; i++){
		int cur = node[i].id;
		int mm = getF(cur);
		res[mm].id = mm;
		res[mm].flag = true;
		res[mm].area += node[i].area;
		res[mm].cnt += node[i].cnt; 
	}
	sort(res, res+maxn, cmp);
	for(cnt = 0; cnt<maxn; cnt++){
		if(res[cnt].flag == false)
			break;
	}
	for(int i = 0; i<cnt; i++){
		int total = 0;
		id = res[i].id;
		for(int j = 0; j<10000; j++){
			if(getF(j) == id) total++;
		}
		res[i].num = total;
		res[i].area /= (1.0*total);
	}
	cout<<cnt<<endl;
	sort(res, res+cnt, cmp2);
	for(int i = 0; i<cnt; i++){
		printf("%04d %d %.3lf %.3f\n", res[i].id, res[i].num, res[i].cnt/(1.0*res[i].num), res[i].area);
	}
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值