#include<stdio.h> #include<iostream> #include<vector> #include<algorithm> using namespace std; int n; struct DATA{ int id, fid,mid , k; int num,people,area; int cid[10]; }data[10001]; int vis[10001] = { 0} ; int father[10001] = {0}; struct Node{ int id; double num,area; int people; int state; }ans[10001]; bool cmp(Node &a,Node &b){ if(a.area != b.area) return a.area > b.area; else a.num<b.num; } int find(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 = find(a); int fb = find(b); if(fa > fb) father[fa] = fb; else if(fa < fb) father[fb] = fa; } int main() { cin>>n; for(int i=0;i<10000;i++) father[i] = i; for(int i=0;i<n;i++){ scanf("%d%d%d%d",&data[i].id,&data[i].fid,&data[i].mid,&data[i].k); vis[data[i].id] = 1 ; if(data[i].fid != -1){ vis[data[i].fid] =1 ; Union(data[i].id,data[i].fid); } if(data[i].mid != -1){ vis[data[i].mid] = 1; Union(data[i].id, data[i].mid); } for(int j=0;j<data[i].k;j++){ scanf("%d",&data[i].cid[j]); vis[data[i].cid[j]]=1; Union(data[i].id,data[i].cid[j]); } scanf("%d%d",&data[i].num,&data[i].area); } for(int i = 0 ;i < n;i++){ // 遍历所有的父节点 int id = find(data[i].id); ans[id].id = id; ans[id].num +=data[i].num; ans[id].area += data[i].area; ans[id].state = 1; } int cnt = 0; for(int i=0;i<10000;i++){ if(vis[i]){ ans[find(i)].people++; } if(ans[i].state) cnt++; } for(int i=0;i<10000;i++) if(ans[i].state){ ans[i].num = ans[i].num*1.0/ans[i].people; ans[i].area = ans[i].area*1.0/ans[i].people; } printf("%d\n",cnt); sort(ans,ans+10000,cmp); for(int i=0;i<cnt ;i++){ printf("%04d %d %.3f %.3f\n",ans[i].id,ans[i].people,ans[i].num,ans[i].area); } return 0; }
1.对于输入数据和输出结果分别定义结构体;
2.对于输出数据中的后两项是由前面数据计算出来的,不用单独定义变量;
3.对于离散的点,题中给了范围,对范围内的所有点的父节点都初始化为本身,通过vis数组判断哪些节点出现过;
4.取最小节点编号,可以在合并的时候不断维护根节点为集合中的最小编号节点;
5.直接通过枚举数据来统计每个集合人数不好统计,枚举每个出现的人找到对应的父节点,在父节点上累加人数。