* 题目描述:
* 给出一颗二叉树,每个节点有一个编号和一个值,该值可能为负数,
* 请你找出一个最优节点(除根节点外),使得在该节点将树分成两棵树后
* (原来的树移除这个节点及其子节点,新的树以该节点为根节点),分成
* 的两棵树各节点的和之间的差绝对值最大。请输出该节点编号,如有多个
* 相同的差,输出编号最小的节点。
*
* 输入描述:
* 4
* 4 9 -7 -8
* 0 1
* 0 3
* 1 2
* 第一行,四个节点,编号0-3,范围为1-10000
* 第二行,节点0-3的权值
* 第三行到第五行,表示二叉树各节点间的父子关系
* 0 1 // 节点0的左节点是1
* 0 2 // 节点0的右节点是2
* 1 2 // 节点1的左节点是2
* 注意:左节点永远出现在右节点之前
* 0:4
* / \
* 1: 9 3:-8
* / \
* /
* 2:-7
* 输出描述:
* 节点编号,示例中编号为3的节点是最优节点
说明:
华为0908第一题
使用方法:不需要将二叉树构建起来,DFS计算每个节点作为root时的树节点的权值和,作为该节点新的权值
解题思路:
其实不需要把树实现出来,只需要关注父节点和子节点的关系
1、题目要求找出一个节点,该节点满足将该树分为两个子树,两个子树之间各节点的和的绝对值最大,假设当前节点为A,以节点A为root点的子树的和为x,很容易求出整树的和sum,那么要使abs(sum-x-(x))最大。所以要想办法求出每个节点以自身为root的子树的权重和来更新该节点的权重;
2、重点问题是按照什么样的顺序更新权值,一定要从叶节点往上更新才是正确的,我一开始想的方法是通过统计节点的入度, 从入度为0的节点开始, 但是由于二叉树是多枝的,不容易实现。既然没办法找出叶节点,那就进行节点的遍历,然后对于每一个普通节点,进行递归更新权值,因为递归的本质就是栈,可以使叶节点的权值先更新。而且二叉树和递归就是天作之合!
代码如下:
#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
// 使用DFS
void dfs(vector<vector<int>>& son, vector<int>& weight, vector<bool>& flag, int node_cur) {
// 当前节点没有子节点时,不需要更新权值, 另外节点的权值已经更新,直接跳过
if (son[node_cur].size() == 0 || flag[node_cur] == true) {
flag[node_cur] = true;
return;
}
// 对于当前节点的权值更新,要先递归更新其当前节点的子节点权值,然后再更新当前节点权值
for (int i = 0; i < son[node_cur].size(); ++i) {
dfs(son, weight, flag, son[node_cur][i]);
weight[node_cur] += weight[son[node_cur][i]];
}
//将已更新的权值的节点标记为true
flag[node_cur] = true;
return;
}
int main() {
int n;
cin >> n;
// 记录每个节点的初始化权值
vector<int> weight(n, 0);
int sum = 0;
for (int i = 0;i < n; ++i) {
cin >> weight[i];
//求所有节点权值和
sum += weight[i];
}
int a, b;
// 存储每个节点的子节点
vector<vector<int>> son(n, vector<int>{});
while (cin >> a >> b) {
son[a].push_back(b);
}
// 记录该节点是否已经更新权值,如果是true,就代表权值更新了;
vector<bool> flag(n, false);
int max_value = 0;
int res;
for (int i = 0; i < n; ++i) {
// 因为一定要从叶子节点向上更新权值才有效,但是确定叶子节点是较困难的,这种方法放弃
// 所以采用遍历每个节点,对于一个普通节点,使用深度遍历递归的更新其子节点的权值
// 这样保证权值的更新不会出现时间先后导致出错的问题
// 然后对于每个已更新权重的节点标记为true,下次遇到的时候就直接过滤掉
dfs(son, weight, flag, i);
if (abs(sum - 2 * weight[i]) > max_value) {
res = i;
max_value = abs(sum - 2 * weight[i]);
}
}
cout << res << endl;
return 0;
}
执行结果如下: