CF1324 Maximum White Subtree 【换根dp】

You are given a tree consisting of 𝑛n vertices. A tree is a connected undirected graph with 𝑛−1n−1 edges. Each vertex 𝑣v of this tree has a color assigned to it (𝑎𝑣=1av=1 if the vertex 𝑣v is white and 00 if the vertex 𝑣v is black).

You have to solve the following problem for each vertex 𝑣v: what is the maximum difference between the number of white and the number of black vertices you can obtain if you choose some subtree of the given tree that contains the vertex 𝑣v? The subtree of the tree is the connected subgraph of the given tree. More formally, if you choose the subtree that contains 𝑐𝑛𝑡𝑤cntw white vertices and 𝑐𝑛𝑡𝑏cntb black vertices, you have to maximize 𝑐𝑛𝑡𝑤−𝑐𝑛𝑡𝑏cntw−cntb.

Input

The first line of the input contains one integer 𝑛n (2≤𝑛≤2⋅1052≤n≤2⋅105) — the number of vertices in the tree.

The second line of the input contains 𝑛n integers 𝑎1,𝑎2,…,𝑎𝑛a1,a2,…,an (0≤𝑎𝑖≤10≤ai≤1), where 𝑎𝑖ai is the color of the 𝑖i-th vertex.

Each of the next 𝑛−1n−1 lines describes an edge of the tree. Edge 𝑖i is denoted by two integers 𝑢𝑖ui and 𝑣𝑖vi, the labels of vertices it connects (1≤𝑢𝑖,𝑣𝑖≤𝑛,𝑢𝑖≠𝑣𝑖(1≤ui,vi≤n,ui≠vi).

It is guaranteed that the given edges form a tree.

Output

Print 𝑛n integers 𝑟𝑒𝑠1,𝑟𝑒𝑠2,…,𝑟𝑒𝑠𝑛res1,res2,…,resn, where 𝑟𝑒𝑠𝑖resi is the maximum possible difference between the number of white and black vertices in some subtree that contains the vertex 𝑖i.

Examples

input

Copy

9
0 1 1 1 0 0 0 0 1
1 2
1 3
3 4
3 5
2 6
4 7
6 8
5 9

output

2 2 2 2 2 1 1 0 2

input

4
0 0 1 0
1 2
1 3
1 4

output

0 -1 1 -1 

#include <bits/stdc++.h>

using namespace std;

const int MAX = 2e5 + 10;

vector<int> e[MAX];
int dp[MAX];

void dfs1(int x, int f) {
    for(auto v: e[x]) {
        if(v == f) continue;
        dfs1(v, x);
        dp[x] += max(0, dp[v]);
    }
}

void dfs2(int x, int f) {
    for(auto v: e[x]) {
        if(v == f) continue;
        dp[v] += max(0, dp[x] - max(0, dp[v]));
        dfs2(v, x);
    }
}

int main() {
    int n;
    cin >> n;
    for(int i = 1, x; i <= n; i++) {
        cin >> x;
        dp[i] = (x == 0 ? -1 : 1);
    }
    for(int i = 1, x, y; i < n; i++) {
        cin >> x >> y;
        e[x].push_back(y);
        e[y].push_back(x);
    }
    dfs1(1, 0);
    dfs2(1, 0);
    for(int i = 1; i <= n; i++) {
        cout << dp[i] << " \n"[i == n];
    }
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值