PAT A1114 Family Property
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
-
思路 1:并查集(带计数版)见 A1118 Birds and Forest
step 1. 输入数据:三个数组inputId
、f_num
、f_erea
:inputId[i]
代表:第i组家庭的首ID;f_num[i]
代表:第i组家庭的房产个数;f_area[i]
代表:第i组家庭的房产面积
step 2. 整合数据:从头遍历这几组数据:
2-1 将每个小家庭的房产数和房产面积累加如大家庭上(大家庭的id为find(inputId[i]);因为Union函数中每次都选id小的做为根:rx<ry
,所以这个id一定是整个家庭里最小的)
2-2 写入家庭总人数,即-father[find(id)]
2-3 把这个大家庭标记上fam[id].flag = true;
step 3. 先按flag位排序将无效数据筛选掉,再进行下一步处理
step 4. 处理数据:求出每个大家庭的平均房产、平均房产面积
step 5. 然后按题目要求:房产面积降序,id升序 , 排序、输出即可 -
code 1:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 10100;
int father[maxn];
struct family{
int id, memNum, num, area;
double avNum, avArea;
bool flag;
family(){id=maxn;}
}fam[maxn];
int find(int x){
while(father[x] >= 0){
x = father[x];
}
return x;
}
void Union(int x, int y){
int rx = find(x);
int ry = find(y);
if(rx != ry){
if(rx > ry){
father[ry]+=father[rx];
father[rx]=ry;
}
else{
father[rx]+=father[ry];
father[ry]=rx;
}
}
}
bool cmp(family a, family b){
return a.flag > b.flag;
}
bool cmp1(family a, family b){
return a.avArea != b.avArea ? a.avArea > b.avArea : a.id < b.id;
}
int inputId[maxn], f_num[maxn], f_area[maxn];
int main(){
int n;
scanf("%d", &n);
fill(father, father+maxn, -1);
for(int i = 0; i < n; ++i){ //1
int fa, ma, nc, tmpc;
scanf("%d %d %d %d", &inputId[i], &fa, &ma, &nc);
if(fa != -1) Union(inputId[i], fa);
if(ma != -1) Union(inputId[i], ma);
for(int j = 0; j < nc; ++j){
scanf("%d", &tmpc);
Union(inputId[i], tmpc);
}
scanf("%d %d", &f_num[i], &f_area[i]);
}
for(int i = 0; i < n; ++i){ //2
int id = find(inputId[i]);
fam[id].id = id;
fam[id].num += f_num[i];
fam[id].area += f_area[i];
fam[id].memNum = -father[id];
fam[id].flag = true;
}
sort(fam, fam+maxn, cmp); //3
int cnt = 0;
for(int i = 0; i < n && fam[i].flag; ++i){ //4
fam[i].avNum = (double)fam[i].num / fam[i].memNum;
fam[i].avArea = (double)fam[i].area / fam[i].memNum;
cnt++;
}
sort(fam, fam+maxn, cmp1); //5
printf("%d\n", cnt);
for(int i = 0; i < cnt; ++i){
printf("%04d %d %.3f %.3f\n", fam[i].id, fam[i].memNum, fam[i].avNum, fam[i].avArea);
}
return 0;
}
-
思路 2:普通并查集
查询家庭人数:通过在结构体中增设一个set<int> family;
,来获得每个家庭的成员,进而得到人数
step 1: 输入n个小家庭,insert成员
step 2:将n个小家庭汇聚成大家庭,成员insert进去,并将大家庭的编号(root)push进一个vector
step 3:对vector下标排序,输出 -
T2 code:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 10010;
int father[maxn];
struct Peo{
int id, sets, area;
unordered_set<int> family;
}peo[maxn];
struct Fam{
int id;
double num, sets, area;
unordered_set<int> family;
}fam[maxn];
void Init(){
for(int i = 0; i < maxn; ++i) father[i] = i;
}
int FindFather(int x){
int tmp = x;
while(father[x] != x){
x = father[x];
}
while(father[tmp] != tmp){
int tmp2 = tmp;
tmp = father[tmp];
father[tmp2] = x;
}
return x;
}
void Union(int a, int b){
int fa = FindFather(a);
int fb = FindFather(b);
if(fa < fb){
father[fb] = fa;
}else{
father[fa] = fb;
}
}
bool cmp(int a, int b){
double avg1 = fam[a].area / fam[a].family.size();
double avg2 = fam[b].area / fam[b].family.size();
return avg1 != avg2 ? avg1 > avg2 : fam[a].id < fam[b].id;
}
bool cnt_fam[maxn];
int main(){
int n;
scanf("%d", &n);
Init();
for(int i = 0; i < n; ++i){
int id, fa, ma, k, num_e, size_e;
scanf("%d %d %d %d", &id, &fa, &ma, &k);
peo[i].family.insert(id);
if(fa != -1){
Union(id, fa);
peo[i].family.insert(fa);
}
if(ma != -1){
Union(id, ma);
peo[i].family.insert(ma);
}
for(int j = 0; j < k; ++j){
int child;
scanf("%d", &child);
Union(id, child);
peo[i].family.insert(child);
}
peo[i].id = id;
scanf("%d %d", &peo[i].sets, &peo[i].area);
}
vector<int> f;
for(int i = 0; i < n; ++i){
int r = FindFather(peo[i].id);
if(cnt_fam[r] == false){
f.push_back(r);
cnt_fam[r] = true;
}
fam[r].id = r;
fam[r].family.insert(peo[i].family.begin(), peo[i].family.end());
fam[r].sets += peo[i].sets;
fam[r].area += peo[i].area;
}
sort(f.begin(), f.end(), cmp);
printf("%d\n", f.size());
for(int i = 0; i < f.size(); ++i){
int now = f[i];
int num = fam[now].family.size();
printf("%04d %d %.3f %.3f\n", fam[now].id, num, fam[now].sets / num, fam[now].area / num);
}
return 0;
}
- T3 code: 直接用结果体作为father,结束是累加出每个大家庭的数据,放到一个vector中排序输出
#include <bits/stdc++.h>
using namespace std;
//const int maxn = 1010; //不止有1000个人,N:家庭数
const int maxn = 100010;
int cnt[maxn], ans_sets[maxn], ans_area[maxn];
unordered_map<int, int> get_id, get_name;
struct Fam
{
int r, np, num_set, area;
double avg_set, avg_area;
}fam[maxn];
void Init()
{
for(int i = 0; i < maxn; ++i)
{
fam[i].r = i;
}
}
int FindFather(int x)
{
int tmp = x;
while(fam[x].r != x)
{
x = fam[x].r;
}
while(fam[tmp].r != tmp)
{
int tmp2 = tmp;
tmp = fam[tmp].r;
fam[tmp2].r = x;
}
return x;
}
void Union(int a, int b)
{
int fa = FindFather(a), fb = FindFather(b);
if(fa != fb)
{
if(get_name[fa] < get_name[fb]) fam[fb].r = fa; //这里必须使用原名字比大小,映射来的没有大小关系
else fam[fa].r = fb;
}
}
int idex = 0;
int Change(int id)
{
if(get_id.find(id) == get_id.end())
{
get_id[id] = idex;
get_name[idex] = id;
return idex++;
}else return get_id[id];
}
bool cmp(Fam a, Fam b)
{
return a.avg_area != b.avg_area ? a.avg_area > b.avg_area : a.r < b.r;
}
int main()
{
int n;
scanf("%d", &n);
Init();
for(int i = 0; i < n; ++i)
{
int tid, other, nch;
scanf("%d", &tid);
tid = Change(tid);
for(int j = 0; j < 2; ++j)
{
scanf("%d", &other);
if(other != -1) Union(tid, Change(other));
}
scanf("%d", &nch);
for(int j = 0; j < nch; ++j)
{
scanf("%d", &other);
Union(tid, Change(other));
}
scanf("%d %d", &fam[tid].num_set, &fam[tid].area);
}
for(int i = 0; i < idex; ++i)
{
int r = FindFather(i);
cnt[r]++;
ans_sets[r] += fam[i].num_set;
ans_area[r] += fam[i].area;
}
vector<Fam> ans;
for(int i = 0; i < idex; ++i)
{
int r = FindFather(i);
if(cnt[r] != 0)
{
ans.push_back(Fam{get_name[r], cnt[r], 0, 0, 1.0*ans_sets[r]/cnt[r], 1.0*ans_area[r]/cnt[r]});
cnt[r] = 0;
}
}
sort(ans.begin(), ans.end(), cmp);
printf("%d\n", ans.size());
for(int i = 0; i < ans.size(); ++i)
{
printf("%04d %d %.3f %.3f\n", ans[i].r, ans[i].np, ans[i].avg_set, ans[i].avg_area);
}
return 0;
}