思路:我们假设节点1为root,如果我们知道了root所有子树的最优情况,那么我们可以把1节点的最优情况传递给它的所有子树(当然如果传递给如图2的子树,那么需要把以2为root的最优贡献给减去,再传递root[1]的最优价值)。那我们这么维护子树的最优情况?很显然,如果子树的价值是负数,那么子树给父结点的价值应该是0,如果是正数,则可以把这个价值传递给父结点。
1 #include <iostream>
2 #include <deque>
3 #include <algorithm>
4 #include <stack>
5 #include <vector>
6 #include <cstring>
7
8 using namespace std;
9
10 const int N = 2e5 + 10;
11
12 struct Tree{
13 int cnt;
14 bool white;
15 }tree[N];
16 struct Edge{
17 int to, nxt;
18 }e[N << 1];
19 int head[N];
20 int n, tot;
21
22 inline void add(int u, int v){
23 e[tot].to = v; e[tot].nxt = head[u]; head[u] = tot++;
24 e[tot].to = u; e[tot].nxt = head[v]; head[v] = tot++;
25 }
26
27 int process(int now, int pre){
28 int cnt = 0;
29 for(int o = head[now]; ~o; o = e[o].nxt){
30 if(e[o].to != pre){
31 cnt += process(e[o].to, now);
32 }
33 }
34 tree[now].cnt = tree[now].white ? 1 : -1; //自身是否是白色
35 tree[now].cnt += cnt > 0 ? cnt : 0; //子树给的价值
36 return max(tree[now].cnt, 0); //返回最优价值
37 }
38
39 void push_down(int now, int pre){
40 for(int o = head[now]; ~o; o = e[o].nxt){
41 if(e[o].to != pre){
42 if(tree[now].cnt > 0){ //如果父结点价值为正,则传递价值
43 //如果该子树价值为正,则父结点传递的价值减去该子树传递的价值
44 //否则直接传递父结点的价值
45 if(tree[e[o].to].cnt > 0) tree[e[o].to].cnt += max(tree[now].cnt - tree[e[o].to].cnt, 0);
46 else tree[e[o].to].cnt += tree[now].cnt;
47 }
48 push_down(e[o].to, now);
49 }
50 }
51 }
52
53 void solve(){
54
55 cin >> n;
56 for(int i = 1; i <= n; ++i) head[i] = -1; tot = 0;
57 for(int i = 1; i <= n; ++i){
58 cin >> tree[i].white;
59 }
60 int u, v;
61 for(int i = 1; i < n; ++i){
62 cin >> u >> v;
63 add(u, v);
64 }
65 process(1, 0);
66 push_down(1, 0);
67 for(int i = 1;i <= n; ++i) cout << tree[i].cnt << " ";
68 cout << endl;
69 }
70
71 int main(){
72
73 ios::sync_with_stdio(false);
74 cin.tie(0);
75 cout.tie(0);
76 solve();
77
78 return 0;
79 }
来源:oschina
链接:https://my.oschina.net/u/4342730/blog/3274209