题意: 给一颗根节点编号为1的树, 节点上都有一个值v[i].
每次对树的"根节点为1"的子树进行所有节点都同时加1或减去1的操作,
求使所有节点为值为0的最小操作次数
分析: 从叶子节点开始做操作使所有子叶为零,
每次取叶子的加的最大值和减去的最大值对父节点操作,
如果父节点不为零, 对父节点操作后更新最新的(加减)操作值,此时此父节点变成叶子节点
直到操作节点规模为0,算法结束
算法: 贪心~, 递归回溯的应用 , 二叉树的遍历
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#include <cmath>
#include <vector>
#include <set>
#include <stack>
#include <algorithm>
//#include "myAlgorithm.h"
#define MAX 100005
#define INF (1e17 + 5)
#define eps 1e-5
using namespace std;
typedef long long ll;
ll getMax(ll a, ll b){return a < b ? b: a;}
vector<vector<int> > adj;
int val[MAX];
int n;
ll ans, add[MAX], red[MAX];
void dfs(int node, int father){
int len = adj[node].size();
for(int i = 0; i < len; i++){
int child = adj[node][i];
if(child != father){
dfs(child, node);
add[node] = getMax(add[child], add[node]);
red[node] = getMax(red[child], red[node]);
}
}
val[node] +=add[node] - red[node];
if(val[node] > 0)red[node] += val[node];
else add[node] += -val[node];
}
void init(){
adj.assign(n+ 2, vector<int>() );
int a, b ;
adj[1].push_back(0);
adj[0].push_back(1);
for(int i = 0; i <n - 1; i++){
cin>>a>>b;
adj[a].push_back(b);
adj[b].push_back(a);
}//input end;
add[0] = red[0] = 0;
for(int i = 1; i <= n; i++){
cin>>val[i];
add[i] = 0;
red[i] = 0;
}
}
int main() {
//freopen("in.txt", "w", stdout);
while(cin>>n){
init();
dfs(1, 0);
cout<<add[1] + red[1]<<endl;
adj.clear();
}
return 0;
}