标签:inner arc a* where related alt 判断 name flag
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.
Each input file contains one test case. For each case, the first line gives a positive integer N (≤1000). Then Nlines follow, each gives the infomation of a person who owns estate in the format:
ID
Father
Mother
k Child?1???Child?k?? M?estate?? Area
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; Child?i??‘s are the ID
‘s of his/her children; M?estate?? is the total number of sets of the real estate under his/her name; and Area
is the total area of his/her estate.
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
AVG?sets?? AVG?area??
where ID
is the smallest ID in the family; M
is the total number of family members; AVG?sets?? is the average number of sets of their real estate; and AVG?area?? is 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.
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
题目大意:找出一个家庭中人均有几套房产,和人均面积;输入中为 当前人的ID 父亲ID 母亲ID 当前人拥有几套 当前人拥有总面积。如果父母去世了,则用-1表示。输出要求按平均房产套数递减,如果相同,那么按ID递增排列。
//确实是使用并查集。
//遇到问题:遇到像8888这种单户的,该怎么处理,我写的里边似乎处理不了。
#include <iostream> #include <algorithm> #include <vector> #include <map> #include<cstdio> using namespace std; struct Peo{ int father,estate,area; Peo(){father=-1;} }peo[10000]; map<int,int> mp; struct Far{ int id,mem; double avge,avga; }; int findF(int a){ if(peo[a].father==-1)return a; int k=peo[a].father; while(peo[k].father!=-1){ peo[a].father=peo[k].father; a=k; k=peo[a].father; //cout<<"wwww"; } //cout<<"fff"; return k; } void unionF(int a,int b){ int fa=findF(a); int fb=findF(b); // if(fa>fb)peo[fa].father=fb; // else peo[fb].father=fa;//这里出现了问题啊,得判断是否等于,等于的话,啥也不用了。 if(fa>fb)peo[fa].father=fb; else if(fa<fb) peo[fb].father=fa; //cout<<"uuuu"; } bool cmp(Far & a,Far & b){ return a.avge!=b.avge?a.id<b.id:a.avge>b.avge; } int main() { int n; cin>>n; //fill(father,father+10000,-1); int id,fa,mo,k,child; for(int i=0;i<n;i++){ cin>>id>>fa>>mo>>k; //先将当前的人和父亲母亲合并 if(fa!=-1) unionF(id,fa); if(mo!=-1) unionF(id,mo); for(int j=0;j<k;j++){ cin>>child; unionF(id,child); } // peo[id].father=id; cin>>peo[id].estate>>peo[id].area; } vector<int> vt[10000]; for(int i=0;i<10000;i++){ if(peo[i].father!=-1){ //cout<<"hh"; mp[peo[i].father]++; //怎么记录每个簇里有谁呢? vt[peo[i].father].push_back(i); } } //最终还得sort一下。 cout<<mp.size()<<‘\n‘; vector<Far> far; for(auto it=mp.begin();it!=mp.end();it++){ int id=it->first; int mem=vt[id].size(); int tote,tota; tote=peo[id].estate; tota=peo[id].area; for(int i=0;i<vt[id].size();i++){ tote+=peo[vt[id][i]].estate; tota+=peo[vt[id][i]].area; } far.push_back(Far{id,mem,tote*1.0/mem,tota*1.0/mem}); } sort(far.begin(),far.end(),cmp); for(int i=0;i<far.size();i++){ printf("%04d %d %.3f %.3f\n",far[i].id,far[i].mem,far[i].avge,far[i].avga); } return 0; }
//写成了这样,最终决定放弃!
代码转自:https://www.liuchuo.net/archives/2201
#include <cstdio> #include <algorithm> using namespace std; struct DATA { int id, fid, mid, num, area; int cid[10];//最多有10个孩子。 }data[1005]; struct node { int id, people; double num, area; bool flag = false; }ans[10000]; int father[10000]; bool visit[10000]; int find(int x) { while(x != father[x])//这样真的好简便,我为啥写那么复杂呢。 x = father[x]; return x; } void Union(int a, int b) { int faA = find(a); int faB = find(b); if(faA > faB) father[faA] = faB; else if(faA < faB) father[faB] = faA; } int cmp1(node a, node b) { if(a.area != b.area) return a.area > b.area; else return a.id < b.id; } int main() { int n, k, cnt = 0; scanf("%d", &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, &k); //直接读进来,不使用中间变量。 //并没有使用下标作为id啊。 visit[data[i].id] = true;//标记出现过了。 if(data[i].fid != -1) { visit[data[i].fid] = true; Union(data[i].fid, data[i].id);//将id作为并查集中的关键字合并。 } if(data[i].mid != -1) { visit[data[i].mid] = true; Union(data[i].mid, data[i].id); } for(int j = 0; j < k; j++) { scanf("%d", &data[i].cid[j]); visit[data[i].cid[j]] = true; Union(data[i].cid[j], data[i].id); } 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作为下标索引了! ans[id].num += data[i].num; ans[id].area += data[i].area; ans[id].flag = true; } for(int i = 0; i < 10000; i++) { if(visit[i])//如果它出现过。 i ans[find(i)].people++; if(ans[i].flag)//标记有几簇人家。 cnt++; } for(int i = 0; i < 10000; i++) { if(ans[i].flag) { ans[i].num = (double)(ans[i].num * 1.0 / ans[i].people); ans[i].area = (double)(ans[i].area * 1.0 / ans[i].people); //并没有多个num属性,都是用一个存的,一开始就设为double。 //我居然还分开定义了。 } } sort(ans, ans + 10000, cmp1); printf("%d\n", cnt); 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.将Father初始化为了自己,那么find函数就简单了,学习了
2.使用一个bool数组来标记出现过的点和没出现过的点,就解决了一家只有一口的情况。
3.在求ans向量的时候,仍使用了find,其实不用map的,find找到父亲都是可以用的。
4.因为data[i].id里存的是已经出现过的id,对那些没出现过的ans.flag肯定不会被标记为true的!
这是错误理解:ans里存储的所有的10000个人的情况,对于那些没有出现过的id,ans[i].flag也是true,只不过它所有的数据都是0,在经过排序之后,再通过簇进行控制输出,其他的不输出。
总之,学习了。
PAT 1114 Family Property[并查集][难]
标签:inner arc a* where related alt 判断 name flag
原文地址:https://www.cnblogs.com/BlueBlueSea/p/9583668.html