输入样例:
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;
typedef long long ll;
const int N = 1e5 + 5;
int f[N];
bool vis[N];
double ans[N],area[N];
struct node{
int id;
int num;
double are,an;
bool operator<(const node& t) const{
if(are != t.are)
return are>t.are;
else
return id<t.id;
}
}p[N];
int find_fa(int x){
return f[x]==x?x:find_fa(f[x]);
}
void _union(int x,int y){
int root_x=find_fa(x),root_y=find_fa(y);
if(root_x!=root_y){
if(root_x>root_y)
f[root_x]=root_y;
else
f[root_y]=root_x;
}
}
int main()
{
int n;
cin>>n;
int id,fa,ma,k,kid,gfa;
for(int i=1;i<=9999;i++) f[i]=i;//并查集初始化
//顺序遍历加入并查集
for(int i=0;i<n;i++)
{
cin>>id>>fa>>ma>>k;
vis[id]=1;
if(fa != -1) _union(fa,id),vis[fa]=1;
if(ma != -1) _union(ma,id),vis[ma]=1;
for(int j=0;j<k;j++)
{
cin>>kid;
vis[kid]=1;
_union(id,kid);
}
cin>>ans[id]>>area[id];//存储房产套数和面积,方便统计集合总套数和总面积
}
set<int>s;//set去重
//将同集合的信息进行统计
for(int i=0;i<=9999;i++)
{
if(vis[i]){
gfa = find_fa(i);
s.insert(gfa);
p[gfa].num++;
p[gfa].are+=area[i];
p[gfa].an +=ans[i];
}
}
cout<<s.size()<<endl;
vector<node>v;
for(set<int>::iterator it = s.begin();it!=s.end();it++){
id = *it;
p[id].id = id;
p[id].an/=p[id].num;
p[id].are/=p[id].num;
v.push_back(p[id]);
}
sort(v.begin(),v.end());
for(int i=0;i<v.size();i++){
cout<<setw(4)<<setfill('0')<<v[i].id<<' '<<v[i].num<<' '<<fixed<<setprecision(3)<<v[i].an<<' '<<fixed<<setprecision(3)<<v[i].are<<endl;
}
return 0;
}