c4-cccc L2-007 家庭房产 并查集

这个题我做了好久,终于用自己的思路Ac了/doge

把每个人做一个集合,其实可以把id,num,house,area,pre这几个数组变成该成这种

class Person {
public:
	int id, num, area, house, pre;
}person[maxn];

对人进行合并操作,每次插入一个人判断这个人是否存在,也就是他的id是否存在,id存在则增加一个人否则不加人只合并,

每次通过find和对minid和person的比较进行合并,只保留其中最高级下表较小的,这样就保证了最后的num不为0的人的id满足要求。这里有个坑点就是把两个下标一样的合并时,由于要被合并者置零,会导致最后很多家庭的全部成员死于莫名AOE,

所以这是应该不操作。

最后把num不为0的人储存在一个vector里,按要求排个序,在输出就可以了。


可以看到速度还是不慢的。


代码如下::

#include<iostream>
#include<cstring>
#include<ctime>
#include<vector>
#include<cstdio>
#include<algorithm>
using namespace std;
#define maxn 10005
int id[maxn], num[maxn], house[maxn], area[maxn], pre[maxn];
typedef struct Ans {
	int id;
	int num;
	double house;
	double area;
	Ans(int id, int num, int house, int area) {
		this->id = id;
		this->num = num;
		this->house = 1.0*house / num;
		this->area = 1.0*area / num;
	}
	void print() {
		printf("%04d %d %.3lf %.3lf\n", id, num, house, area);
	}
};
int find(int i) {
	if (pre[i] == i)return i;
	else {
		return i=find(pre[i]);
	}
}
int un(int number, int minid) {
	if (number != -1) {
		if (id[number]) {
			id[number] = 0;
			if (number != pre[number]) {
				number = find(number);
			}
			num[number]++;
		}
		else {
			if (number != pre[number]) {
				number = find(number);
			}
		}
		if (number < minid) {//合并number和minid
			num[number] += num[minid];
			house[number] += house[minid];
			area[number] += area[minid];
			num[minid] = 0;
			house[minid] = 0;
			area[minid] = 0;
			pre[minid] = number;
			minid = number;
		}
		else if(number>minid){
			num[minid] += num[number];
			house[minid] += house[number];
			area[minid] += area[number];
			num[number] = 0;
			house[number] = 0;
			area[number] = 0;
			pre[number] = minid;
		}
	}
	return minid;
}
vector<Ans> ans;
bool cmp(const Ans a, const Ans b) {
	if (a.area == b.area)return a.id < b.id;
	return a.area > b.area;
}
int main(int argc,char argv[]) {
	int minid;
	int t;//numOfHouses
	int k;//numOfKids
	int number;//numberOfPerson
	int s;//areas
	int n;//house
	cin >> t;
	for (int i = 0; i < maxn; i++) {
		pre[i] = i;
		num[i] = 0;
		id[i] = 1;
	}
	while (t--) {
		cin >> minid;
		if (id[minid]) {
			id[minid] = 0;
			if (minid != pre[minid]) {
				minid = find(minid);
			}
			num[minid]++;
		}
		else {
			if (minid != pre[minid]) {
				minid = find(minid);
			}
		}
		cin >> number;
		if(number!=-1)
			minid = un(number, minid);
		cin >> number;
		if (number!=-1)
			minid = un(number, minid);
		cin >> k;
		while (k--) {
			cin >> number;
			if (number!=-1)
				minid = un(number, minid);
		}
		cin >> n >> s;
		area[minid] += s;
		house[minid] += n;
	}
	int x  ;
	for (int i = 0; i < maxn; i++) {
		if (num[i] != 0) {
			x = find(i);
			if (x < i) {
				un(i, x);
			}
			else {
				un(x, i);
			}
		}
	}
	for (int i = 0; i < maxn; i++) {
		if (num[i] != 0) {
			ans.push_back(Ans(i, num[i], house[i], area[i]));
		}
	}
	printf("%d\n", ans.size());
	sort(ans.begin(), ans.end(), cmp);
	for (Ans i : ans) {
		i.print();
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41104612/article/details/79514391