PAT Family Property DFS+哈希

该博客主要介绍了如何通过哈希映射和深度优先搜索(DFS)来解决涉及家庭成员关系的问题。在题目中,每个人被视为一个节点,如果两人之间存在家庭关系,则建立双向边。博客作者分享了自己在实现过程中遇到的两个错误:一是边的建立应为双向,二是数组大小预估不足。最后,通过DFS遍历找到每个家庭的所有成员,并计算家庭的平均房屋数量和面积。文章以C++代码展示了解决方案,并对结果进行了排序。
摘要由CSDN通过智能技术生成

题目链接

思路:
本题将每个人作为一个单独的结点,若两个人之间是家人关系,则建立边关系。通过哈希法建立人名与编号,编号与人名之间的映射。最后统计每个家庭的人数时,用DFS遍历即可。

对于本题我犯过两个错误,仅供读者参考:
1.建立边关系的时候,应当建立双向边,而不是单向边。
2.出现的人数比较大,数组开大一点。

参考代码:

#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;

unordered_map<string, int> ConvertToInt;  //形成人名与编号之间的映射
unordered_map<int, string> ConvertToString;  //形成编号与人名之间的映射
vector<int> e[1005];  //建立图(邻接表形式)
int snum[1005] = { 0 }, area[1005] = { 0 };  //snum表示编号为i的人拥有的房屋数量, area同理

bool vis[1005];  //表示dfs遍历种结点是否被访问过
int sumnum, sumarea, people;  //表示在每轮dfs遍历中,这个家庭的总房屋数,总面积, 总人数
string sumname;  //表示在每轮dfs遍历中,字典序最小的名字
void dfs(int index)
{
	vis[index] = true;
	sumnum += snum[index];
	sumarea += area[index];
	people++;
	if (ConvertToString[index] < sumname)
		sumname = ConvertToString[index];

	for (auto x : e[index])
	{
		if (vis[x] == false)
			dfs(x);
	}
}

struct node {  //表示家庭信息的结构体
	string name;
	double num, area;
	int people;
	node(string a, double b, double c, int d) {
		name = a, num = b, area = c, people = d;;
	}
};

bool cmp(node& a, node& b)
{
	if (a.area == b.area) return a.name < b.name;
	else return a.area > b.area;
}

int main()
{
	int n;
	cin >> n;
	int t = 0;
	while (n--)
	{
		string id, father, mother, child;
		int k, tnum, tarea;
		cin >> id >> father >> mother >> k;
		if (!ConvertToInt.count(id))
		{
			ConvertToInt[id] = t;
			ConvertToString[t] = id;
			t++;
		}
		int top = ConvertToInt[id];

		vector<string> v;  //创建数组,存放家人编号
		if (father != "-1") v.emplace_back(father);
		if (mother != "-1") v.emplace_back(mother);
		for (int i = 0; i < k;i++)
		{
			cin >> child;
			v.emplace_back(child);
		}
		for (auto name : v)
		{
			if (!ConvertToInt.count(name))
			{
				ConvertToInt[name] = t;
				ConvertToString[t] = name;
				t++;
			}
			e[top].emplace_back(ConvertToInt[name]);
			e[ConvertToInt[name]].emplace_back(top);
		}
		
		cin >> tnum >> tarea;
		snum[top] = tnum;  //存入房屋拥有者的房屋套数信息
		area[top] = tarea;  //存入房屋拥有者的房屋面积信息
	}
	
	vector<node> res;  //存放最终的家庭信息
	for (int i = 0; i < t;i++)
		if (vis[i] == false)
		{
			sumarea = 0, sumnum = 0, people = 0;
			sumname = ConvertToString[i];
			dfs(i);
			res.push_back(node(sumname, 1.0 * sumnum / people, 1.0 * sumarea / people, people));
		}

	sort(res.begin(), res.end(), cmp);  //按题目要求进行家庭排序
	cout << res.size() << endl;
	for (auto info : res)
	{
		cout << info.name;
		printf(" %d %.3f %.3f\n", info.people, info.num, info.area);
	}

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值