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 Mestate 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; 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 AVGarea 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.
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
题目大意
给定一些人员信息,包括他们的父母,子女,有多少房产,总共多少面积。
要求按照格式输出一个家族的人员数量、人均拥有房产套数、人均拥有房产面积。最前面的识别符ID为家族中ID最小的那个人的。
分析
使用并查集,合并属于同一个家族的,在合并的过程中,更新房产信息。
首先将人员信息存储入info字典,将每条输入中的所有ID存储入man列表。
实例化unionfind实例。
使用items属性存储去重之后的所有人员的ID,使用item存储每次输入获取的当前行的所有ID。
使用root属性记录当前节点的根节点。使用result存储当前节点所属家族的房产总套数、总面积以及总人数。
在main()函数中调用实例u的create()方法。构建森林,合并集合。
item中的每一个元素来说,如果它包含了一个以上的元素,则遍历它。对它里面的元素进行遍历时,如果发现相邻的两个元素的根节点不同,就合并这两个节点。
比较这两个节点的根节点哪个比较小,将根节点比较大的那颗树合并到根节点较小的那棵树下面,更新小根节点的家族的信息,并删除大根节点。
Python实现
class unionfind:
def __init__(self, man, info):
self.items = []
self.item, self.info = man, info
for x in self.item:
self.items += x
self.items = list(set(self.items))
self.root, self.result = {}, {}
for x in self.items:
self.root[x] = x
try:
self.result[x] = self.info[x][-2:]+[1]
except:
self.result[x] = [0,0,1]
def create(self):
for x in self.item:
if len(x) > 1:
for i in range(1,len(x)):
root1, root2 = self.findroot(x[i-1]), self.findroot(x[i])
if root1 != root2:
self.union(root1, root2)
def findroot(self, x):
if x in self.result.keys():
return x
else:
return self.findroot(self.root[x])
def union(self, root1, root2):
if root1<root2:
self.root[root2] = root1
self.result[root1][0] += self.result[root2][0]
self.result[root1][1] += self.result[root2][1]
self.result[root1][2] += self.result[root2][2]
self.result.pop(root2)
else:
self.root[root1] = root2
self.result[root2][0] += self.result[root1][0]
self.result[root2][1] += self.result[root1][1]
self.result[root2][2] += self.result[root1][2]
self.result.pop(root1)
def main():
n = int(input())
info, man = {}, []
for x in range(n):
line = input().split(" ")
ID, fa, mo = line[0], line[1] ,line[2]
k, m, a = int(line[3]), int(line[-2]), int(line[-1])
info[ID] = [m,a]
unit = [ID]
if fa !='-1':
unit.append(fa)
if mo !='-1':
unit.append(mo)
unit += line[4 : 4 + k]
man.append(unit)
u = unionfind(man,info)
u.create()
result = sorted(u.result, key = lambda x : (-u.result[x][1]/u.result[x][2],int(x)))
print(len(result))
for x in result:
print(x,u.result[x][2],'{:.3f}'.format(u.result[x][0]/u.result[x][2]),'{:.3f}'.format(u.result[x][1]/u.result[x][2]))
if __name__ == "__main__":
main()