This time, you are supposed to help us collect the data for family-owned property. Given each person's family members, and the estate(房产)info under his/her own name, we need to know the size of each family, and the average area and number of sets of their real estate.
Input Specification:
Each input file contains one test case. For each case, the first line gives a positive integer N (≤1000). Then N lines follow, each gives the infomation of a person who owns estate in the format:
ID
Father
Mother
k Child1⋯Childk MestateArea
where ID
is a unique 4-digit identification number for each person; Father
and Mother
are the ID
's of this person's parents (if a parent has passed away, -1
will be given instead); k (0≤k≤5) is the number of children of this person; Childi's are the ID
's of his/her children; Mestate is the total number of sets of the real estate under his/her name; and Area
is the total area of his/her estate.
Output Specification:
For each case, first print in a line the number of families (all the people that are related directly or indirectly are considered in the same family). Then output the family info in the format:
ID
M
AVGsets AVGarea
where ID
is the smallest ID in the family; M
is the total number of family members; AVGsets is the average number of sets of their real estate; and AVGareais the average area. The average numbers must be accurate up to 3 decimal places. The families must be given in descending order of their average areas, and in ascending order of the ID's if there is a tie.
Sample Input:
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
Sample Output:
3
8888 1 1.000 1000.000
0001 15 0.600 100.000
5551 4 0.750 100.000
题目大意:给定每个人的家庭成员和其自己名下的房产,请你统计出每个家庭的人口数、人均房产面积及房产套数。首先在第一行输出家庭个数(所有有亲属关系的人都属于同一个家庭)。随后按下列格式输出每个家庭的信息:家庭成员的最小编号 家庭人口数 人均房产套数 人均房产面积。其中人均值要求保留小数点后3位。家庭信息首先按人均面积降序输出,若有并列,则按成员编号的升序输出。
代码一:DFS
首先对每个成员(父母、孩子进行编码),然后DFS,连通块个数就是家庭的个数,Head为DFS参数,若当前元素id更小则更新Head,同时计算总人数,房产总面积以及房产套数。
#include<cstdio>
#include<map>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn = 10000;
struct node{
int sets=0,totalA=0;
vector<int> member;
}peo[maxn];
struct node2{
int id, M;
double AvgS, AvgA;
};
vector<node2> ans;
map<int, int> m;
map<int, int> i_id;
bool visit[maxn];
int index = 1;
bool cmp(node2 a, node2 b){
return a.AvgA != b.AvgA ? a.AvgA > b.AvgA:a.id < b.id;
}
void code(int id){ //编码
m[id] = index;
i_id[index] = id;
index++;
}
void dfs(int now,int &Head,int &M,int &totalS,int &totalA){
visit[now] = true;
M++;
if (i_id[now] < i_id[Head]) Head = now;
totalA += peo[now].totalA;
totalS += peo[now].sets;
for (auto x : peo[now].member) {
if(!visit[x])dfs(x, Head, M, totalS, totalA);
}
}
int main(){
int N;
int id, fa, mo, k, c;
scanf("%d", &N);
//编码,存储
for (int i = 0; i < N; i++){
scanf("%d%d%d%d", &id, &fa, &mo,&k);
if (!m[id]) code(id);
if (!m[fa] && fa != -1)code(fa);
if (fa != -1){
peo[m[id]].member.push_back(m[fa]);
peo[m[fa]].member.push_back(m[id]);
}
if (!m[mo] && mo != -1)code(mo);
if (mo != -1){
peo[m[id]].member.push_back(m[mo]);
peo[m[mo]].member.push_back(m[id]);
}
for (int j = 0; j < k; j++){
scanf("%d", &c);
if (!m[c])code(c);
peo[m[id]].member.push_back(m[c]);
peo[m[c]].member.push_back(m[id]);
}
scanf("%d%d", &peo[m[id]].sets, &peo[m[id]].totalA);
}
for (int i = 1; i < index;i++){
int Head = i, M = 0, totalS = 0, totalA = 0;
if (!visit[i]){
dfs(i, Head, M, totalS, totalA);
int head = i_id[Head];
node2 t;
t.id = head; t.M = M; t.AvgS = totalS*(1.0) / M; t.AvgA = totalA*(1.0) / M;
ans.push_back(t);
}
}
sort(ans.begin(), ans.end(),cmp);
printf("%d\n", ans.size());
for (auto it = ans.begin(); it != ans.end(); it++){
printf("%04d %d %.3lf %.3lf\n", it->id, it->M, it->AvgS, it->AvgA);
}
}
代码二:并查集
参考柳神博客
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 10000;
struct node{
int id, M, A;
}data[1005]; //保存数据
struct node2{
int id, members=0;
double avgS=0.0, avgA=0.0;
bool isFather = false; //标记是否根节点
}ans[maxn]; //以id为索引存储答案的散列
bool cmp(node2 a, node2 b){
return a.avgA != b.avgA ? a.avgA > b.avgA:a.id < b.id;
}
bool visit[maxn];
int father[maxn];
int findFather(int x){
return x == father[x] ? x : father[x] = findFather(father[x]);
}
void Union(int a, int b){
int fa = findFather(a);
int fb = findFather(b);
if (fa > fb)swap(fa, fb);
father[fb] = fa;
}
int main(){
int N;
scanf("%d", &N);
for (int i = 0; i < maxn; i++)father[i] = i;
int fid, mid, cid,k;
//建立集合
for (int i = 0; i <N; i++){
scanf("%d%d%d%d", &data[i].id, &fid, &mid, &k);
visit[data[i].id] = true;
if (fid != -1){
visit[fid] = true;
Union(data[i].id, fid);
}
if (mid != -1){
visit[mid] = true;
Union(data[i].id, mid);
}
for (int j = 0; j < k; j++){
scanf("%d", &cid);
visit[cid] = true;
Union(data[i].id, cid);
}
scanf("%d%d", &data[i].M, &data[i].A);
}
//置根节点
for (int i = 0; i < N; i++){
int id = findFather(data[i].id);
ans[id].id = id;
ans[id].avgS += data[i].M;
ans[id].avgA += data[i].A;
ans[id].isFather = true;
}
//统计各家庭人数、总家庭数
int cnt = 0;
for (int i = 0; i < maxn; i++){
if (visit[i])ans[findFather(i)].members++;
if (ans[i].isFather)cnt++;
}
//计算均值
for (int i = 0; i < maxn; i++) {
if (ans[i].isFather) {
ans[i].avgS = (double)(ans[i].avgS * 1.0 / ans[i].members);
ans[i].avgA = (double)(ans[i].avgA * 1.0 / ans[i].members);
}
}
sort(ans, ans + maxn, cmp);
printf("%d\n", cnt);
for (int i = 0; i < cnt; i++)printf("%04d %d %.3lf %.3lf\n", ans[i].id, ans[i].members, ans[i].avgS, ans[i].avgA);
}