PTA链接1114 Family Property (25分)
最怕这种没有难度但是极其耗时的题目。做这类题目事先一定要规划好,画好逻辑图,不能想到哪写到哪,脑子一团浆糊往往能磨蹭的写一个多小时。
题目梗概:
给出一个数n,接下来有n个家庭,每个家庭包括一定的成员,房产数和房产总面积。如果不同的家庭中有相同的成员,则这些家庭可以组成一个家族。求计算有几个家族,输出每个家族中ID最小的,家族成员数,房产数/成员数,房产面积/成员数。
解题流程:
1.创建并查集,创建N个父节点,使一个家庭的全部成员为对应父节点的子集。
2.如果其中一个家庭的父节点为A,但是其中有一个成员已经有归属的父节点B,则将A的父节点设为B从而形成一个家族。
例如:
7777 6666 -1 0 2 300
6666 5551 5552 1 7777 1 100
这两个家庭就能形成一个家族。
3.合并家庭的同时将家庭的资产也同时合并。
AC代码
#include<cstdio>
#include<vector>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=1010;
int n,father[11010];
double area[maxn],sets[maxn];
set<int> person; //储存成员id
vector<int> family;//储存家族
struct Node{
int id;
int meb;
double set;
double area;
}node[maxn];
int findFather(int x){
int a=x;
while(x!=father[x]){
x=father[x];
}
while(a!=father[a]){
int z=a;
a=father[a];
father[z]=x;
}
return x;
}
void Union(int a,int b){
int fa=findFather(a);
int fb=findFather(b);
if(fa!=fb){
father[fb]=fa;
}
}
bool cmp(int a,int b){
if(node[a].area==node[b].area){
return node[a].id<node[b].id;
}
else return node[a].area>node[b].area;
}
int main(){
//freopen("input.txt","r",stdin);
scanf("%d",&n);
int start=10000; //每个家庭的父节点从start开始计数(0~9999为家庭成员的父节点)
for(int i=0;i<11010;i++){
father[i]=i; //初始化父节点
}
int id,k;
for(int i=start;i<start+n;i++){ //i为该家庭的父节点
for(int j=0;j<3;j++){
scanf("%d",&id);
if(id==-1){ //家庭成员不存在则跳过
continue;
}
person.insert(id);
if(id!=father[id]){ //该成员已经属于其他家庭
int flag=findFather(id); //将两个家庭合并
Union(i,flag);
}
father[id]=i;
}
scanf("%d",&k);
for(int j=0;j<k;j++){
scanf("%d",&id);
person.insert(id);
if(id!=father[id]){
int flag=father[id];
Union(i,flag);
}
father[id]=i;
}
scanf("%lf %lf",&sets[i-start],&area[i-start]);
}
for(int i=start;i<n+start;i++){ //资产合并
k=findFather(i);
if(k!=i){
sets[k-start]+=sets[i-start];
area[k-start]+=area[i-start];
}
}
for(int i=start;i<start+n;i++){ //家族创建
if(i==father[i]){
k=i-start;
node[k].area=area[k];
node[k].set=sets[k];
node[k].meb=0;
node[k].id=10000;
family.push_back(k);
}
}
for(set<int>::iterator it=person.begin();it!=person.end();it++){ //遍历所有人口
int id=*it;
k=findFather(id)-start;
if(node[k].id>id){
node[k].id=id;
}
node[k].meb++;
}
for(int i=0;i<family.size();i++){
k=family[i];
node[k].set=node[k].set/node[k].meb*1.0;
node[k].area=node[k].area/node[k].meb*1.0;
}
sort(family.begin(),family.end(),cmp);
printf("%d\n",family.size());
for(int i=0;i<family.size();i++){
k=family[i];
printf("%04d %d %.3f %.3f\n",node[k].id,node[k].meb,node[k].set,node[k].areid);
}
return 0;
}