简单的树(summary)

实验任务

可怜的 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;
}



很多可能会因为看到是树的问题就被束缚起来不会往这个方向想,我就是这样,但愿以后可以发散思维。

原文地址:https://www.cnblogs.com/heihuifei/p/7800815.html