思路:
本题将每个人作为一个单独的结点,若两个人之间是家人关系,则建立边关系。通过哈希法建立人名与编号,编号与人名之间的映射。最后统计每个家庭的人数时,用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;
}