算法与数据结构实验题 6.4 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

思路

建立结构体

struct Tree
{
	int value;           //储存小偷数量
	int father;          //储存父节点
	int max;             //储存以这个节点为根的子节点小偷最大值
	int sum;             //以该节点为根的子树中小偷数量的总和
};

从最后一个节点开始,把它的value值加到它的父节点sum值上,并和父节点的max值比较,更新这个max值。

以询问节点为根的子树:两颗子树都要以这个节点为根节点

这就意味着:在我们统计max和sum的时候也要把被查询的节点的数据算进去。

Code

 
            #include<stdio.h>
#include<iostream>
using namespace std;
struct Tree
{
	int value;
	int father;
	int max;
	int sum;
};
int _max(int x,int y)
{
	if(x>y)return x;
	else return y;
}
Tree tree[100001]={0};
int main()
{
	int i;
	int max=0;
	int x;
	int y;
	int n;
	int m;
	int temp;
	scanf("%d",&n);
	for(i=2;i<=n;i++)
	{
		scanf("%d %d",&x,&y);
		tree[i].father=x;
		tree[i].value=y;
	}
	for(i=n;i>=1;i--)
	{
		tree[i].sum+=tree[i].value;                   //把自身的value加到sum中,作为最后的sum
		tree[i].max=_max(tree[i].max,tree[i].value);  //用自身的value和子树所提供的value最大值进行比较,得到最后的max
		tree[tree[i].father].sum=tree[tree[i].father].sum+tree[i].sum;
		temp=_max(tree[i].value,tree[i].max);
		if(temp>tree[tree[i].father].max)tree[tree[i].father].max=temp;
	}
	scanf("%d",&m);
	for(i=1;i<=m;i++)
	{
		scanf("%d",&x);
		printf("%d %d",tree[x].sum,tree[x].max);
		if(i<n)printf("
");
	}
	return 0;
}
        
原文地址:https://www.cnblogs.com/031602523liu/p/7816222.html