[CF1324F] Maximum White Subtree

题目链接

Solution

如果只询问根节点的答案,那是一道很简单的 $dp$ 题:设 $dp[i]$ 是以 $i$ 为根的子树的答案,$dfs$ 一遍就能得到答案。

现在考虑换根的问题,如果根节点从 $x$ 换成与之相邻的 $y$,可以发现 $dp$ 值改变的只有 $dp[x]$ 和 $dp[y]$,且 dp[x] -= max(0, dp[y]), dp[y] += max(0, dp[x]) 即可。于是再 $dfs$ 一遍得到所有点的答案。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include<algorithm>
#include<cstdio>

using namespace std;

typedef long long LL;

const int N = 200005;

int n, a[N], ans[N];

struct Edge{
int nxt, to;
}edge[N<<1];
int head[N], edgeNum;
void addEdge(int from, int to){
edge[++edgeNum] = (Edge){head[from], to};
head[from] = edgeNum;
}

int res[N];
int dfs(int x, int f){
for(int i = head[x]; i; i = edge[i].nxt){
if(edge[i].to == f) continue;
res[x] += max(0, dfs(edge[i].to, x));
}
return res[x];
}

void dfsAns(int x, int f){
ans[x] = res[x];
for(int i = head[x]; i; i = edge[i].nxt){
if(edge[i].to == f) continue;
res[x] -= max(0, res[edge[i].to]);
res[edge[i].to] += max(0, res[x]);
dfsAns(edge[i].to, x);
res[edge[i].to] -= max(0, res[x]);
res[x] += max(0, res[edge[i].to]);
}
}

int main(){
scanf("%d", &n);
for(int i = 1; i <= n; i++){
scanf("%d", &a[i]);
res[i] = a[i] == 1 ? 1 : -1;
}
for(int i = 1; i < n; i++){
int u, v; scanf("%d%d", &u, &v);
addEdge(u, v), addEdge(v, u);
}
dfs(1, 0);
dfsAns(1, 0);
for(int i = 1; i <= n; i++)
printf("%d ", ans[i]);
return 0;
}
作者

xyfJASON

发布于

2020-03-13

更新于

2021-02-25

许可协议

评论