zoukankan      html  css  js  c++  java
  • PAT (Advanced Level) Practice 1114 Family Property (25分) (并查集+标记)

    1.题目

    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 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.

    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 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.

    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

    2.题目分析

    没超时没爆内存很是欣慰

    1.使用并查集来寻找最小的ID

    2.node2用来存放已给出节点的set以及area(有的节点的父母未给出set,area,这里只存放第一列ID以及其对应的set、area)

    然后使用list2进行标记(开始想着遍历寻找可能会超时,就使用了标记)

    3.unordered_set<int>ids;用来存放所有出现过的ID(-1除外),包括后面的父母、孩子

    4.unordered_set<int>unique;用来存放所有的祖先节点

    5.node用来存放最后要输出的一个总家庭的人数、平均set、评价area,放入set<node, cmp>out;输出 

    注意:代码中:if (find(*it2) == *it)//不能是father[*it2]==*it

    即使经过路径压缩,最后每个节点的父亲都不一定是最后的祖先!!!!!所以在判断节点是不是祖先的时候不能直接使用father【】,而要使用find()!!!

    3.代码

    #include<iostream>
    #include<set>
    #include<unordered_set>
    using namespace std;
    int father[10001];
    struct node
    {
    	int id;
    	int mcount;
    	double avsets;
    	double avarea;
    };
    struct node2
    {
    	int id;
    	int mcount;
    	double area;
    }list2[10001];
    struct cmp
    {
    	bool operator () (const node &a, const node &b)
    	{
    		if (a.avarea == b.avarea)return a.id < b.id;
    		return a.avarea > b.avarea;
    	}
    };
    int find(int x)
    {
    	if (father[x] == x)return x;
    	return father[x]=find(father[x]);
    }
    
    void unions(int x, int y)
    {
    	int a = find(x);
    	int b =find(y);
    	if (a == b)return;
    	if (a > b)father[a] = b;
    	if (a < b)father[b] = a;
    }
    int main()
    {
    	int n,a,b;
    	scanf("%d", &n);
    	for (int i = 0; i < 10001; i++)
    		father[i] = i;
    	unordered_set<int>ids;
    	unordered_set<int>unique;
    	set<node, cmp>out;
    	for (int i = 0; i < n; i++)
    	{
    		int k, c, mark, m;
    		double areas;
    		scanf("%d %d %d", &mark, &a, &b);
    		ids.insert(mark);
    		scanf("%d", &k);
    		for (int j = 0; j < k; j++)
    		{
    			scanf("%d", &c);
    			ids.insert(c);
    			unions(mark, c);
    		}
    		scanf("%d %lf", &m, &areas);
    		list2[mark].id = mark; list2[mark].mcount = m; list2[mark].area = areas;
    		if (a != -1) { ids.insert(a); unions(mark, a); }
    		if (b != -1) { ids.insert(b); unions(mark, b); }
    	}
    
    	for (auto it = ids.begin(); it != ids.end(); it++)
    	{
    		int aaaaa = father[*it];
    		if (*it == father[*it])
    			unique.insert(*it);
    	}
    	for (auto it = unique.begin(); it != unique.end(); it++)
    	{
    		int m = 0; double sumset = 0, sumarea = 0;
    		for (auto it2 = ids.begin(); it2 != ids.end(); it2++)
    		{
    			if (find(*it2) == *it)//这里注意不能是father[*it2]==*it
    			{
    				m++;
    				sumset += list2[*it2].mcount;
    				sumarea += list2[*it2].area;
    			}
    		}
    		out.insert(node{*it,m,sumset/m,sumarea/m});
    	}
    
    	printf("%d
    ", out.size());
    	for (auto it = out.begin(); it != out.end(); it++)
    	{
    		printf("%04d %d %.3f %.3f
    ", it ->id, it->mcount, it->avsets, it->avarea);
    	}
    
    }
  • 相关阅读:
    扩展中国剩余定理
    bzoj 3816&&uoj #41. [清华集训2014]矩阵变换
    THUSC2017
    bzoj 4521: [Cqoi2016]手机号码
    bzoj 4871: [Shoi2017]摧毁“树状图”
    bzoj 2300 : [HAOI2011]防线修建
    bzoj 3853 : GCD Array
    HEOI 2017 游记
    bzoj3926: [Zjoi2015]诸神眷顾的幻想乡 广义后缀自动机模板
    bzoj 4310 跳蚤
  • 原文地址:https://www.cnblogs.com/Jason66661010/p/12788855.html
Copyright © 2011-2022 走看看