实验任务
可怜的 Bibi 丢了好几台手机以后,看谁都像是小偷,他已经在小本本上记下了他认为的各个地点的小偷数量。 现在我们将Bibi的家附近的地形抽象成一棵有根树。每个地点都是树上的 一个节点,节点上都标注了 Bibi 心中该地点的小偷数量。现在 Bibi 告诉你一个 节点 k,请你求出以该节点为根的子树中小偷数量的总和,以及子树中小偷最多 的节点的小偷数量。
★数据输入
输入第一行为一个正整数 n(1≤n≤100000)表示树的节点数目,树根的编号 总是为 1,且没有小偷。 接下来 n-1 行,每行两个正整数 p,x(1≤x≤100)。代表编号为 i 的节点的父 亲节点 p 和该节点的小偷数量 x。数据保证输入的 p 小于当前的 i。这里的 i 从 2 依次数到 n。 第 n+1 行一个整数 m(1≤m≤n), 表示询问组数。 第 n+2 行有 m 个整数,每个整数 ki(1≤ki≤n)代表该组询问中的节点 k。
★数据输出
输出 m 行,每行两个整数,代表以询问节点为根的子树中小偷数量的总和, 以及子树中小偷最多的节点的小偷数量。
测试样例:
输入:
3
1 56
1 82
1
1
输出:
138 82
解题过程:最开始对这题的思路陷入了死胡同,只考虑到通过记录儿子节点然后查找儿子实现,这样实现起来很多局限性,而且效率可能不高,我还因为对链表的使用不熟没能实现。之后同学交流得知新思路。
思路:通过数组嵌套存储父节点就行了,看完之后甚至会觉得不是在做树的问题。
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
int b[100000];
struct node
{
int fa;
int max;
int sum;
}a[100000];
int main()
{
int n;
cin >> n;
int i;
a[1].max = a[1].sum = 0;
for (i = 2; i <= n; i++)
{
cin >> a[i].fa >> a[i].max;
a[i].sum = a[i].max;
}
for (i = n; i > 1; i--)
{
a[a[i].fa].sum += a[i].sum;
a[a[i].fa].max = (a[i].max > a[a[i].fa].max) ? a[i].max : a[a[i].fa].max;
}
int m;
cin >> m;
for (i = 1; i <= m; i++)
{
cin >> b[i];
}
for (i = 1; i <= m; i++)
{
cout << a[b[i]].sum << " " << a[b[i]].max << endl;
}
return 0;
}
很多可能会因为看到是树的问题就被束缚起来不会往这个方向想,我就是这样,但愿以后可以发散思维。