You are given a tree consisting of $$$n$$$ vertices. A tree is a connected undirected graph with $$$n-1$$$ edges. Each vertex $$$v$$$ of this tree has a color assigned to it ($$$a_v = 1$$$ if the vertex $$$v$$$ is white and $$$0$$$ 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 $$$cnt_w$$$ white vertices and $$$cnt_b$$$ black vertices, you have to maximize $$$cnt_w - cnt_b$$$.

The first line of the input contains one integer $$$n$$$ ($$$2 \le n \le 2 \cdot 10^5$$$) — the number of vertices in the tree. The second line of the input contains $$$n$$$ integers $$$a_1, a_2, \dots, a_n$$$ ($$$0 \le a_i \le 1$$$), where $$$a_i$$$ is the color of the $$$i$$$-th vertex. Each of the next $$$n-1$$$ lines describes an edge of the tree. Edge $$$i$$$ is denoted by two integers $$$u_i$$$ and $$$v_i$$$, the labels of vertices it connects $$$(1 \le u_i, v_i \le n, u_i \ne v_i$$$). It is guaranteed that the given edges form a tree.

Print $$$n$$$ integers $$$res_1, res_2, \dots, res_n$$$, where $$$res_i$$$ is the maximum possible difference between the number of white and black vertices in some subtree that contains the vertex $$$i$$$.

NoteThe first example is shown below:The black vertices have bold borders.In the second example, the best subtree for vertices $$$2, 3$$$ and $$$4$$$ are vertices $$$2, 3$$$ and $$$4$$$ correspondingly. And the best subtree for the vertex $$$1$$$ is the subtree consisting of vertices $$$1$$$ and $$$3$$$.

/*
URL:
https://codeforces.com/problemset/problem/1324/F
*/

package main

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"math"
	"os"
	"strconv"
)

/********** FAU standard libraries **********/

//fmt.Sprintf("%b\n", 255) 	// binary expression

/********** I/O usage **********/

//str := ReadString()
//i := ReadInt()
//X := ReadIntSlice(n)
//S := ReadRuneSlice()
//a := ReadFloat64()
//A := ReadFloat64Slice(n)

//str := ZeroPaddingRuneSlice(num, 32)
//str := PrintIntsLine(X...)

/*******************************************************************/

const (
	// General purpose
	MOD = 1000000000 + 7
	// MOD          = 998244353
	ALPHABET_NUM = 26
	INF_INT64    = math.MaxInt64
	INF_BIT60    = 1 << 60
	INF_INT32    = math.MaxInt32
	INF_BIT30    = 1 << 30
	NIL          = -1

	// for dijkstra, prim, and so on
	WHITE = 0
	GRAY  = 1
	BLACK = 2
)

func init() {
	// bufio.ScanWords <---> bufio.ScanLines
	ReadString = newReadString(os.Stdin, bufio.ScanWords)
	stdout = bufio.NewWriter(os.Stdout)
}

var (
	n     int
	A     []int
	edges [][]int
)

func main() {
	n = ReadInt()
	A = ReadIntSlice(n)
	for i := 0; i < n-1; i++ {
		x, y := ReadInt2()
		x--
		y--

		e := []int{x, y}
		edges = append(edges, e)
	}

	f := func(x, y T) T {
		res := T(0)
		if x > 0 {
			res += x
		}
		if y > 0 {
			res += y
		}
		return res
	}
	g := func(v T, node int) T {
		var diff T
		if A[node] == 0 {
			diff = -1
		} else {
			diff = 1
		}
		return v + diff
	}
	s := NewReRootingSolver(n, edges, 0, f, g)

	ans := []int{}
	for i := 0; i < n; i++ {
		ans = append(ans, int(s.Query(i)))
	}
	fmt.Println(PrintIntsLine(ans...))
}

type T int

type ReRootingSolver struct {
	NodeCount int

	Adjacents         [][]int
	IndexForAdjacents [][]int

	Res []T
	DP  [][]T

	Identity    T
	Operate     func(l, r T) T
	OperateNode func(v T, p int) T
}

func NewReRootingSolver(
	nodeCount int, edges [][]int, identity T, operate func(l, r T) T, operateNode func(v T, p int) T,
) *ReRootingSolver {
	s := new(ReRootingSolver)

	s.NodeCount = nodeCount
	s.Identity = identity
	s.Operate = operate
	s.OperateNode = operateNode

	s.Adjacents = make([][]int, nodeCount)
	s.IndexForAdjacents = make([][]int, nodeCount)
	for _, e := range edges {
		s.IndexForAdjacents[e[0]] = append(s.IndexForAdjacents[e[0]], len(s.Adjacents[e[1]]))
		s.IndexForAdjacents[e[1]] = append(s.IndexForAdjacents[e[1]], len(s.Adjacents[e[0]]))
		s.Adjacents[e[0]] = append(s.Adjacents[e[0]], e[1])
		s.Adjacents[e[1]] = append(s.Adjacents[e[1]], e[0])
	}

	s.DP = make([][]T, len(s.Adjacents))
	s.Res = make([]T, len(s.Adjacents))

	for i := 0; i < len(s.Adjacents); i++ {
		s.DP[i] = make([]T, len(s.Adjacents[i]))
	}

	if s.NodeCount > 1 {
		s.Initialize()
	} else {
		s.Res[0] = s.OperateNode(s.Identity, 0)
	}

	return s
}

func (s *ReRootingSolver) Query(node int) T {
	return s.Res[node]
}

func (s *ReRootingSolver) Initialize() {
	parents, order := make([]int, s.NodeCount), make([]int, s.NodeCount)

	// InitOrderedTree
	index := 0
	stack := []int{}
	stack = append(stack, 0)
	parents[0] = -1
	for len(stack) > 0 {
		node := stack[len(stack)-1]
		stack = stack[:len(stack)-1]
		order[index] = node
		index++
		for i := 0; i < len(s.Adjacents[node]); i++ {
			adjacent := s.Adjacents[node][i]
			if adjacent == parents[node] {
				continue
			}
			stack = append(stack, adjacent)
			parents[adjacent] = node
		}
	}

	// fromLeaf
	for i := len(order) - 1; i >= 1; i-- {
		node := order[i]
		parent := parents[node]

		accum := s.Identity
		parentIndex := -1
		for j := 0; j < len(s.Adjacents[node]); j++ {
			if s.Adjacents[node][j] == parent {
				parentIndex = j
				continue
			}
			accum = s.Operate(accum, s.DP[node][j])
		}
		s.DP[parent][s.IndexForAdjacents[node][parentIndex]] = s.OperateNode(accum, node)
	}

	// toLeaf
	for i := 0; i < len(order); i++ {
		node := order[i]
		accum := s.Identity
		accumsFromTail := make([]T, len(s.Adjacents[node]))
		accumsFromTail[len(accumsFromTail)-1] = s.Identity
		for j := len(accumsFromTail) - 1; j >= 1; j-- {
			accumsFromTail[j-1] = s.Operate(s.DP[node][j], accumsFromTail[j])
		}
		for j := 0; j < len(accumsFromTail); j++ {
			s.DP[s.Adjacents[node][j]][s.IndexForAdjacents[node][j]] = s.OperateNode(s.Operate(accum, accumsFromTail[j]), node)
			accum = s.Operate(accum, s.DP[node][j])
		}
		s.Res[node] = s.OperateNode(accum, node)
	}
}

/*******************************************************************/

/*********** I/O ***********/

var (
	// ReadString returns a WORD string.
	ReadString func() string
	stdout     *bufio.Writer
)

func newReadString(ior io.Reader, sf bufio.SplitFunc) func() string {
	r := bufio.NewScanner(ior)
	r.Buffer(make([]byte, 1024), int(1e+9)) // for Codeforces
	r.Split(sf)

	return func() string {
		if !r.Scan() {
			panic("Scan failed")
		}
		return r.Text()
	}
}

// ReadInt returns an integer.
func ReadInt() int {
	return int(readInt64())
}
func ReadInt2() (int, int) {
	return int(readInt64()), int(readInt64())
}
func ReadInt3() (int, int, int) {
	return int(readInt64()), int(readInt64()), int(readInt64())
}
func ReadInt4() (int, int, int, int) {
	return int(readInt64()), int(readInt64()), int(readInt64()), int(readInt64())
}

// ReadInt64 returns as integer as int64.
func ReadInt64() int64 {
	return readInt64()
}
func ReadInt64_2() (int64, int64) {
	return readInt64(), readInt64()
}
func ReadInt64_3() (int64, int64, int64) {
	return readInt64(), readInt64(), readInt64()
}
func ReadInt64_4() (int64, int64, int64, int64) {
	return readInt64(), readInt64(), readInt64(), readInt64()
}

func readInt64() int64 {
	i, err := strconv.ParseInt(ReadString(), 0, 64)
	if err != nil {
		panic(err.Error())
	}
	return i
}

// ReadIntSlice returns an integer slice that has n integers.
func ReadIntSlice(n int) []int {
	b := make([]int, n)
	for i := 0; i < n; i++ {
		b[i] = ReadInt()
	}
	return b
}

// ReadInt64Slice returns as int64 slice that has n integers.
func ReadInt64Slice(n int) []int64 {
	b := make([]int64, n)
	for i := 0; i < n; i++ {
		b[i] = ReadInt64()
	}
	return b
}

// ReadFloat64 returns an float64.
func ReadFloat64() float64 {
	return float64(readFloat64())
}

func readFloat64() float64 {
	f, err := strconv.ParseFloat(ReadString(), 64)
	if err != nil {
		panic(err.Error())
	}
	return f
}

// ReadFloatSlice returns an float64 slice that has n float64.
func ReadFloat64Slice(n int) []float64 {
	b := make([]float64, n)
	for i := 0; i < n; i++ {
		b[i] = ReadFloat64()
	}
	return b
}

// ReadRuneSlice returns a rune slice.
func ReadRuneSlice() []rune {
	return []rune(ReadString())
}

/*********** Debugging ***********/

// ZeroPaddingRuneSlice returns binary expressions of integer n with zero padding.
// For debugging use.
func ZeroPaddingRuneSlice(n, digitsNum int) []rune {
	sn := fmt.Sprintf("%b", n)

	residualLength := digitsNum - len(sn)
	if residualLength <= 0 {
		return []rune(sn)
	}

	zeros := make([]rune, residualLength)
	for i := 0; i < len(zeros); i++ {
		zeros[i] = '0'
	}

	res := []rune{}
	res = append(res, zeros...)
	res = append(res, []rune(sn)...)

	return res
}

// Strtoi is a wrapper of strconv.Atoi().
// If strconv.Atoi() returns an error, Strtoi calls panic.
func Strtoi(s string) int {
	if i, err := strconv.Atoi(s); err != nil {
		panic(errors.New("[argument error]: Strtoi only accepts integer string"))
	} else {
		return i
	}
}

// PrintIntsLine returns integers string delimited by a space.
func PrintIntsLine(A ...int) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.Itoa(A[i])
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// PrintIntsLine returns integers string delimited by a space.
func PrintInts64Line(A ...int64) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.FormatInt(A[i], 10) // 64bit int version
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// PrintfDebug is wrapper of fmt.Fprintf(os.Stderr, format, a...)
func PrintfDebug(format string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, format, a...)
}

// PrintfBufStdout is function for output strings to buffered os.Stdout.
// You may have to call stdout.Flush() finally.
func PrintfBufStdout(format string, a ...interface{}) {
	fmt.Fprintf(stdout, format, a...)
}

/*
URL:
https://codeforces.com/problemset/problem/1324/F
*/

package main

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"math"
	"os"
	"strconv"
)

/********** FAU standard libraries **********/

//fmt.Sprintf("%b\n", 255) 	// binary expression

/********** I/O usage **********/

//str := ReadString()
//i := ReadInt()
//X := ReadIntSlice(n)
//S := ReadRuneSlice()
//a := ReadFloat64()
//A := ReadFloat64Slice(n)

//str := ZeroPaddingRuneSlice(num, 32)
//str := PrintIntsLine(X...)

/*******************************************************************/

const (
	// General purpose
	MOD = 1000000000 + 7
	// MOD          = 998244353
	ALPHABET_NUM = 26
	INF_INT64    = math.MaxInt64
	INF_BIT60    = 1 << 60
	INF_INT32    = math.MaxInt32
	INF_BIT30    = 1 << 30
	NIL          = -1

	// for dijkstra, prim, and so on
	WHITE = 0
	GRAY  = 1
	BLACK = 2
)

func init() {
	// bufio.ScanWords <---> bufio.ScanLines
	ReadString = newReadString(os.Stdin, bufio.ScanWords)
	stdout = bufio.NewWriter(os.Stdout)
}

var (
	n int
	A []int

	G [200000 + 50][]int
	// dp      [200000 + 50]int
	// answers [200000 + 50]int
)

func main() {
	n = ReadInt()
	A = ReadIntSlice(n)
	for i := 0; i < n-1; i++ {
		a, b := ReadInt2()
		a--
		b--

		G[a] = append(G[a], b)
		G[b] = append(G[b], a)
	}

	f := func(x, y T) T {
		res := T(0)
		if x > 0 {
			res += x
		}
		if y > 0 {
			res += y
		}
		return res
	}
	g := func(v T, node int) T {
		var diff T
		if A[node] == 0 {
			diff = -1
		} else {
			diff = 1
		}
		return v + diff
	}
	s := NewReRooting(n, G[:n], 0, f, g)
	ans := []int{}
	for i := 0; i < n; i++ {
		ans = append(ans, int(s.Query(i)))
	}
	fmt.Println(PrintIntsLine(ans...))

	// dfs1(0, -1)
	// PrintfDebug("%v\n", dp[:n])
	// dfs2(0, -1, 0)
	// fmt.Println(PrintIntsLine(answers[:n]...))
}

// func dfs2(cid, pid, dpar int) {
// 	dchilds := []int{}
// 	nexts := []int{}
// 	for _, nid := range G[cid] {
// 		if nid == pid {
// 			continue
// 		}
// 		dchilds = append(dchilds, dp[nid])
// 		nexts = append(nexts, nid)
// 	}

// 	// cidの答えを計算
// 	root := 0
// 	if A[cid] == 0 {
// 		root--
// 	} else {
// 		root++
// 	}
// 	other := 0
// 	for _, v := range dchilds {
// 		other += Max(v, 0)
// 	}
// 	other += Max(dpar, 0)
// 	answers[cid] = root + other

// 	l := len(dchilds)
// 	if l == 0 {
// 		return
// 	}
// 	if l == 1 {
// 		dfs2(nexts[0], cid, root+Max(dpar, 0))
// 		return
// 	}

// 	// 子が2つ以上の場合
// 	R, L := make([]int, l), make([]int, l)
// 	L[0] = Max(dchilds[0], 0)
// 	for i := 1; i < l; i++ {
// 		L[i] = L[i-1] + Max(dchilds[i], 0)
// 	}
// 	R[l-1] = Max(dchilds[l-1], 0)
// 	for i := l - 2; i >= 0; i-- {
// 		R[i] = R[i+1] + Max(dchilds[i], 0)
// 	}
// 	for i, nid := range nexts {
// 		if i == 0 {
// 			dfs2(nid, cid, root+R[1]+Max(dpar, 0))
// 		} else if i == l-1 {
// 			dfs2(nid, cid, root+L[l-2]+Max(dpar, 0))
// 		} else {
// 			dfs2(nid, cid, root+L[i-1]+R[i+1]+Max(dpar, 0))
// 		}
// 	}
// }

// func dfs1(cid, pid int) int {
// 	res := 0
// 	if A[cid] == 0 {
// 		res--
// 	} else {
// 		res++
// 	}

// 	for _, nid := range G[cid] {
// 		if nid == pid {
// 			continue
// 		}
// 		res += Max(dfs1(nid, cid), 0)
// 	}

// 	dp[cid] = res
// 	return res
// }

type T int

type ReRooting struct {
	n int
	G [][]int

	ti      T
	dp, res []T
	merge   func(l, r T) T
	addNode func(t T, idx int) T
}

func NewReRooting(
	n int, AG [][]int, ti T, merge func(l, r T) T, addNode func(t T, idx int) T,
) *ReRooting {
	s := new(ReRooting)
	s.n, s.G, s.ti, s.merge, s.addNode = n, AG, ti, merge, addNode
	s.dp, s.res = make([]T, n), make([]T, n)

	s.Solve()

	return s
}

func (s *ReRooting) Solve() {
	s.inOrder(0, -1)
	s.reroot(0, -1, s.ti)
}

func (s *ReRooting) Query(idx int) T {
	return s.res[idx]
}

func (s *ReRooting) inOrder(cid, pid int) T {
	res := s.ti

	for _, nid := range G[cid] {
		if nid == pid {
			continue
		}

		res = s.merge(res, s.inOrder(nid, cid))
	}
	res = s.addNode(res, cid)
	s.dp[cid] = res

	return s.dp[cid]
}

func (s *ReRooting) reroot(cid, pid int, parentValue T) {
	childValues := []T{}
	nexts := []int{}
	for _, nid := range G[cid] {
		if nid == pid {
			continue
		}
		childValues = append(childValues, s.dp[nid])
		nexts = append(nexts, nid)
	}

	// result of cid
	rootValue := s.ti
	for _, v := range childValues {
		rootValue = s.merge(rootValue, v)
	}
	rootValue = s.merge(rootValue, parentValue)
	rootValue = s.addNode(rootValue, cid)
	s.res[cid] = rootValue

	// for children
	accum := s.merge(s.ti, parentValue)
	length := len(childValues)
	if length == 0 {
		return
	}
	if length == 1 {
		s.reroot(nexts[0], cid, s.addNode(accum, cid))
		return
	}

	// cid has more than one child
	R, L := make([]T, length), make([]T, length)
	L[0] = s.merge(s.ti, childValues[0])
	for i := 1; i < length; i++ {
		L[i] = s.merge(L[i-1], childValues[i])
	}
	R[length-1] = s.merge(s.ti, childValues[length-1])
	for i := length - 2; i >= 0; i-- {
		R[i] = s.merge(R[i+1], childValues[i])
	}

	for i, nid := range nexts {
		if i == 0 {
			s.reroot(nid, cid, s.addNode(s.merge(accum, R[1]), cid))
		} else if i == length-1 {
			s.reroot(nid, cid, s.addNode(s.merge(accum, L[length-2]), cid))
		} else {
			s.reroot(nid, cid, s.addNode(s.merge(accum, s.merge(L[i-1], R[i+1])), cid))
		}
	}
}

// Max returns the max integer among input set.
// This function needs at least 1 argument (no argument causes panic).
func Max(integers ...int) int {
	m := integers[0]
	for i, integer := range integers {
		if i == 0 {
			continue
		}
		if m < integer {
			m = integer
		}
	}
	return m
}

/*******************************************************************/

/*********** I/O ***********/

var (
	// ReadString returns a WORD string.
	ReadString func() string
	stdout     *bufio.Writer
)

func newReadString(ior io.Reader, sf bufio.SplitFunc) func() string {
	r := bufio.NewScanner(ior)
	r.Buffer(make([]byte, 1024), int(1e+9)) // for Codeforces
	r.Split(sf)

	return func() string {
		if !r.Scan() {
			panic("Scan failed")
		}
		return r.Text()
	}
}

// ReadInt returns an integer.
func ReadInt() int {
	return int(readInt64())
}
func ReadInt2() (int, int) {
	return int(readInt64()), int(readInt64())
}
func ReadInt3() (int, int, int) {
	return int(readInt64()), int(readInt64()), int(readInt64())
}
func ReadInt4() (int, int, int, int) {
	return int(readInt64()), int(readInt64()), int(readInt64()), int(readInt64())
}

// ReadInt64 returns as integer as int64.
func ReadInt64() int64 {
	return readInt64()
}
func ReadInt64_2() (int64, int64) {
	return readInt64(), readInt64()
}
func ReadInt64_3() (int64, int64, int64) {
	return readInt64(), readInt64(), readInt64()
}
func ReadInt64_4() (int64, int64, int64, int64) {
	return readInt64(), readInt64(), readInt64(), readInt64()
}

func readInt64() int64 {
	i, err := strconv.ParseInt(ReadString(), 0, 64)
	if err != nil {
		panic(err.Error())
	}
	return i
}

// ReadIntSlice returns an integer slice that has n integers.
func ReadIntSlice(n int) []int {
	b := make([]int, n)
	for i := 0; i < n; i++ {
		b[i] = ReadInt()
	}
	return b
}

// ReadInt64Slice returns as int64 slice that has n integers.
func ReadInt64Slice(n int) []int64 {
	b := make([]int64, n)
	for i := 0; i < n; i++ {
		b[i] = ReadInt64()
	}
	return b
}

// ReadFloat64 returns an float64.
func ReadFloat64() float64 {
	return float64(readFloat64())
}

func readFloat64() float64 {
	f, err := strconv.ParseFloat(ReadString(), 64)
	if err != nil {
		panic(err.Error())
	}
	return f
}

// ReadFloatSlice returns an float64 slice that has n float64.
func ReadFloat64Slice(n int) []float64 {
	b := make([]float64, n)
	for i := 0; i < n; i++ {
		b[i] = ReadFloat64()
	}
	return b
}

// ReadRuneSlice returns a rune slice.
func ReadRuneSlice() []rune {
	return []rune(ReadString())
}

/*********** Debugging ***********/

// ZeroPaddingRuneSlice returns binary expressions of integer n with zero padding.
// For debugging use.
func ZeroPaddingRuneSlice(n, digitsNum int) []rune {
	sn := fmt.Sprintf("%b", n)

	residualLength := digitsNum - len(sn)
	if residualLength <= 0 {
		return []rune(sn)
	}

	zeros := make([]rune, residualLength)
	for i := 0; i < len(zeros); i++ {
		zeros[i] = '0'
	}

	res := []rune{}
	res = append(res, zeros...)
	res = append(res, []rune(sn)...)

	return res
}

// Strtoi is a wrapper of strconv.Atoi().
// If strconv.Atoi() returns an error, Strtoi calls panic.
func Strtoi(s string) int {
	if i, err := strconv.Atoi(s); err != nil {
		panic(errors.New("[argument error]: Strtoi only accepts integer string"))
	} else {
		return i
	}
}

// PrintIntsLine returns integers string delimited by a space.
func PrintIntsLine(A ...int) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.Itoa(A[i])
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// PrintIntsLine returns integers string delimited by a space.
func PrintInts64Line(A ...int64) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.FormatInt(A[i], 10) // 64bit int version
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// PrintfDebug is wrapper of fmt.Fprintf(os.Stderr, format, a...)
func PrintfDebug(format string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, format, a...)
}

// PrintfBufStdout is function for output strings to buffered os.Stdout.
// You may have to call stdout.Flush() finally.
func PrintfBufStdout(format string, a ...interface{}) {
	fmt.Fprintf(stdout, format, a...)
}

/*
URL:
https://codeforces.com/problemset/problem/1324/F
*/

package main

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"math"
	"os"
	"strconv"
)

/********** FAU standard libraries **********/

//fmt.Sprintf("%b\n", 255) 	// binary expression

/********** I/O usage **********/

//str := ReadString()
//i := ReadInt()
//X := ReadIntSlice(n)
//S := ReadRuneSlice()
//a := ReadFloat64()
//A := ReadFloat64Slice(n)

//str := ZeroPaddingRuneSlice(num, 32)
//str := PrintIntsLine(X...)

/*******************************************************************/

const (
	// General purpose
	MOD = 1000000000 + 7
	// MOD          = 998244353
	ALPHABET_NUM = 26
	INF_INT64    = math.MaxInt64
	INF_BIT60    = 1 << 60
	INF_INT32    = math.MaxInt32
	INF_BIT30    = 1 << 30
	NIL          = -1

	// for dijkstra, prim, and so on
	WHITE = 0
	GRAY  = 1
	BLACK = 2
)

func init() {
	// bufio.ScanWords <---> bufio.ScanLines
	ReadString = newReadString(os.Stdin, bufio.ScanWords)
	stdout = bufio.NewWriter(os.Stdout)
}

var (
	n int
	A []int

	G       [200000 + 50][]int
	dp      [200000 + 50]int
	answers [200000 + 50]int
)

func main() {
	n = ReadInt()
	A = ReadIntSlice(n)
	for i := 0; i < n-1; i++ {
		a, b := ReadInt2()
		a--
		b--

		G[a] = append(G[a], b)
		G[b] = append(G[b], a)
	}

	dfs1(0, -1)
	PrintfDebug("%v\n", dp[:n])
	dfs2(0, -1, 0)

	fmt.Println(PrintIntsLine(answers[:n]...))
}

func dfs2(cid, pid, dpar int) {
	dchilds := []int{}
	nexts := []int{}
	for _, nid := range G[cid] {
		if nid == pid {
			continue
		}
		dchilds = append(dchilds, dp[nid])
		nexts = append(nexts, nid)
	}

	// cidの答えを計算
	root := 0
	if A[cid] == 0 {
		root--
	} else {
		root++
	}
	other := 0
	for _, v := range dchilds {
		other += Max(v, 0)
	}
	other += Max(dpar, 0)
	answers[cid] = root + other

	l := len(dchilds)
	if l == 0 {
		return
	}
	if l == 1 {
		dfs2(nexts[0], cid, root+Max(dpar, 0))
		return
	}

	// 子が2つ以上の場合
	R, L := make([]int, l), make([]int, l)
	L[0] = Max(dchilds[0], 0)
	for i := 1; i < l; i++ {
		L[i] = L[i-1] + Max(dchilds[i], 0)
	}
	R[l-1] = Max(dchilds[l-1], 0)
	for i := l - 2; i >= 0; i-- {
		R[i] = R[i+1] + Max(dchilds[i], 0)
	}
	for i, nid := range nexts {
		if i == 0 {
			dfs2(nid, cid, root+R[1]+Max(dpar, 0))
		} else if i == l-1 {
			dfs2(nid, cid, root+L[l-2]+Max(dpar, 0))
		} else {
			dfs2(nid, cid, root+L[i-1]+R[i+1]+Max(dpar, 0))
		}
	}
}

func dfs1(cid, pid int) int {
	res := 0
	if A[cid] == 0 {
		res--
	} else {
		res++
	}

	for _, nid := range G[cid] {
		if nid == pid {
			continue
		}
		res += Max(dfs1(nid, cid), 0)
	}

	dp[cid] = res
	return res
}

// Max returns the max integer among input set.
// This function needs at least 1 argument (no argument causes panic).
func Max(integers ...int) int {
	m := integers[0]
	for i, integer := range integers {
		if i == 0 {
			continue
		}
		if m < integer {
			m = integer
		}
	}
	return m
}

/*******************************************************************/

/*********** I/O ***********/

var (
	// ReadString returns a WORD string.
	ReadString func() string
	stdout     *bufio.Writer
)

func newReadString(ior io.Reader, sf bufio.SplitFunc) func() string {
	r := bufio.NewScanner(ior)
	r.Buffer(make([]byte, 1024), int(1e+9)) // for Codeforces
	r.Split(sf)

	return func() string {
		if !r.Scan() {
			panic("Scan failed")
		}
		return r.Text()
	}
}

// ReadInt returns an integer.
func ReadInt() int {
	return int(readInt64())
}
func ReadInt2() (int, int) {
	return int(readInt64()), int(readInt64())
}
func ReadInt3() (int, int, int) {
	return int(readInt64()), int(readInt64()), int(readInt64())
}
func ReadInt4() (int, int, int, int) {
	return int(readInt64()), int(readInt64()), int(readInt64()), int(readInt64())
}

// ReadInt64 returns as integer as int64.
func ReadInt64() int64 {
	return readInt64()
}
func ReadInt64_2() (int64, int64) {
	return readInt64(), readInt64()
}
func ReadInt64_3() (int64, int64, int64) {
	return readInt64(), readInt64(), readInt64()
}
func ReadInt64_4() (int64, int64, int64, int64) {
	return readInt64(), readInt64(), readInt64(), readInt64()
}

func readInt64() int64 {
	i, err := strconv.ParseInt(ReadString(), 0, 64)
	if err != nil {
		panic(err.Error())
	}
	return i
}

// ReadIntSlice returns an integer slice that has n integers.
func ReadIntSlice(n int) []int {
	b := make([]int, n)
	for i := 0; i < n; i++ {
		b[i] = ReadInt()
	}
	return b
}

// ReadInt64Slice returns as int64 slice that has n integers.
func ReadInt64Slice(n int) []int64 {
	b := make([]int64, n)
	for i := 0; i < n; i++ {
		b[i] = ReadInt64()
	}
	return b
}

// ReadFloat64 returns an float64.
func ReadFloat64() float64 {
	return float64(readFloat64())
}

func readFloat64() float64 {
	f, err := strconv.ParseFloat(ReadString(), 64)
	if err != nil {
		panic(err.Error())
	}
	return f
}

// ReadFloatSlice returns an float64 slice that has n float64.
func ReadFloat64Slice(n int) []float64 {
	b := make([]float64, n)
	for i := 0; i < n; i++ {
		b[i] = ReadFloat64()
	}
	return b
}

// ReadRuneSlice returns a rune slice.
func ReadRuneSlice() []rune {
	return []rune(ReadString())
}

/*********** Debugging ***********/

// ZeroPaddingRuneSlice returns binary expressions of integer n with zero padding.
// For debugging use.
func ZeroPaddingRuneSlice(n, digitsNum int) []rune {
	sn := fmt.Sprintf("%b", n)

	residualLength := digitsNum - len(sn)
	if residualLength <= 0 {
		return []rune(sn)
	}

	zeros := make([]rune, residualLength)
	for i := 0; i < len(zeros); i++ {
		zeros[i] = '0'
	}

	res := []rune{}
	res = append(res, zeros...)
	res = append(res, []rune(sn)...)

	return res
}

// Strtoi is a wrapper of strconv.Atoi().
// If strconv.Atoi() returns an error, Strtoi calls panic.
func Strtoi(s string) int {
	if i, err := strconv.Atoi(s); err != nil {
		panic(errors.New("[argument error]: Strtoi only accepts integer string"))
	} else {
		return i
	}
}

// PrintIntsLine returns integers string delimited by a space.
func PrintIntsLine(A ...int) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.Itoa(A[i])
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// PrintIntsLine returns integers string delimited by a space.
func PrintInts64Line(A ...int64) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.FormatInt(A[i], 10) // 64bit int version
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// PrintfDebug is wrapper of fmt.Fprintf(os.Stderr, format, a...)
func PrintfDebug(format string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, format, a...)
}

// PrintfBufStdout is function for output strings to buffered os.Stdout.
// You may have to call stdout.Flush() finally.
func PrintfBufStdout(format string, a ...interface{}) {
	fmt.Fprintf(stdout, format, a...)
}

/*
URL:
https://codeforces.com/problemset/problem/1324/F
*/

package main

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"math"
	"os"
	"strconv"
)

/********** FAU standard libraries **********/

//fmt.Sprintf("%b\n", 255) 	// binary expression

/********** I/O usage **********/

//str := ReadString()
//i := ReadInt()
//X := ReadIntSlice(n)
//S := ReadRuneSlice()
//a := ReadFloat64()
//A := ReadFloat64Slice(n)

//str := ZeroPaddingRuneSlice(num, 32)
//str := PrintIntsLine(X...)

/*******************************************************************/

const (
	// General purpose
	MOD = 1000000000 + 7
	// MOD          = 998244353
	ALPHABET_NUM = 26
	INF_INT64    = math.MaxInt64
	INF_BIT60    = 1 << 60
	INF_INT32    = math.MaxInt32
	INF_BIT30    = 1 << 30
	NIL          = -1

	// for dijkstra, prim, and so on
	WHITE = 0
	GRAY  = 1
	BLACK = 2
)

func init() {
	// bufio.ScanWords <---> bufio.ScanLines
	ReadString = newReadString(os.Stdin, bufio.ScanWords)
	stdout = bufio.NewWriter(os.Stdout)
}

var (
	n int
	A []int

	G [200000 + 50][]int
)

func main() {
	n = ReadInt()
	A = ReadIntSlice(n)
	for i := 0; i < n-1; i++ {
		a, b := ReadInt2()
		a--
		b--

		G[a] = append(G[a], b)
		G[b] = append(G[b], a)
	}

	f := func(l, r T) T {
		res := T(0)
		if l > 0 {
			res += l
		}
		if r > 0 {
			res += r
		}
		return res
	}
	g := func(t T, idx int) T {
		var diff T
		if A[idx] == 0 {
			diff = -1
		} else {
			diff = 1
		}
		return t + diff
	}
	s := NewReRooting(n, G[:n], 0, f, g)
	ans := []int{}
	for i := 0; i < n; i++ {
		ans = append(ans, int(s.Query(i)))
	}
	fmt.Println(PrintIntsLine(ans...))
}

type T int

type ReRooting struct {
	n int
	G [][]int

	ti      T
	dp, res []T
	merge   func(l, r T) T
	addNode func(t T, idx int) T
}

func NewReRooting(
	n int, AG [][]int, ti T, merge func(l, r T) T, addNode func(t T, idx int) T,
) *ReRooting {
	s := new(ReRooting)
	s.n, s.G, s.ti, s.merge, s.addNode = n, AG, ti, merge, addNode
	s.dp, s.res = make([]T, n), make([]T, n)

	s.Solve()

	return s
}

func (s *ReRooting) Solve() {
	s.inOrder(0, -1)
	s.reroot(0, -1, s.ti)
}

func (s *ReRooting) Query(idx int) T {
	return s.res[idx]
}

func (s *ReRooting) inOrder(cid, pid int) T {
	res := s.ti

	for _, nid := range G[cid] {
		if nid == pid {
			continue
		}

		res = s.merge(res, s.inOrder(nid, cid))
	}
	res = s.addNode(res, cid)
	s.dp[cid] = res

	return s.dp[cid]
}

func (s *ReRooting) reroot(cid, pid int, parentValue T) {
	childValues := []T{}
	nexts := []int{}
	for _, nid := range G[cid] {
		if nid == pid {
			continue
		}
		childValues = append(childValues, s.dp[nid])
		nexts = append(nexts, nid)
	}

	// result of cid
	rootValue := s.ti
	for _, v := range childValues {
		rootValue = s.merge(rootValue, v)
	}
	rootValue = s.merge(rootValue, parentValue)
	rootValue = s.addNode(rootValue, cid)
	s.res[cid] = rootValue

	// for children
	accum := s.merge(s.ti, parentValue)
	length := len(childValues)
	if length == 0 {
		return
	}
	if length == 1 {
		s.reroot(nexts[0], cid, s.addNode(accum, cid))
		return
	}

	// cid has more than one child
	R, L := make([]T, length), make([]T, length)
	L[0] = s.merge(s.ti, childValues[0])
	for i := 1; i < length; i++ {
		L[i] = s.merge(L[i-1], childValues[i])
	}
	R[length-1] = s.merge(s.ti, childValues[length-1])
	for i := length - 2; i >= 0; i-- {
		R[i] = s.merge(R[i+1], childValues[i])
	}

	for i, nid := range nexts {
		if i == 0 {
			s.reroot(nid, cid, s.addNode(s.merge(accum, R[1]), cid))
		} else if i == length-1 {
			s.reroot(nid, cid, s.addNode(s.merge(accum, L[length-2]), cid))
		} else {
			s.reroot(nid, cid, s.addNode(s.merge(accum, s.merge(L[i-1], R[i+1])), cid))
		}
	}
}

// Max returns the max integer among input set.
// This function needs at least 1 argument (no argument causes panic).
func Max(integers ...int) int {
	m := integers[0]
	for i, integer := range integers {
		if i == 0 {
			continue
		}
		if m < integer {
			m = integer
		}
	}
	return m
}

/*******************************************************************/

/*********** I/O ***********/

var (
	// ReadString returns a WORD string.
	ReadString func() string
	stdout     *bufio.Writer
)

func newReadString(ior io.Reader, sf bufio.SplitFunc) func() string {
	r := bufio.NewScanner(ior)
	r.Buffer(make([]byte, 1024), int(1e+9)) // for Codeforces
	r.Split(sf)

	return func() string {
		if !r.Scan() {
			panic("Scan failed")
		}
		return r.Text()
	}
}

// ReadInt returns an integer.
func ReadInt() int {
	return int(readInt64())
}
func ReadInt2() (int, int) {
	return int(readInt64()), int(readInt64())
}
func ReadInt3() (int, int, int) {
	return int(readInt64()), int(readInt64()), int(readInt64())
}
func ReadInt4() (int, int, int, int) {
	return int(readInt64()), int(readInt64()), int(readInt64()), int(readInt64())
}

// ReadInt64 returns as integer as int64.
func ReadInt64() int64 {
	return readInt64()
}
func ReadInt64_2() (int64, int64) {
	return readInt64(), readInt64()
}
func ReadInt64_3() (int64, int64, int64) {
	return readInt64(), readInt64(), readInt64()
}
func ReadInt64_4() (int64, int64, int64, int64) {
	return readInt64(), readInt64(), readInt64(), readInt64()
}

func readInt64() int64 {
	i, err := strconv.ParseInt(ReadString(), 0, 64)
	if err != nil {
		panic(err.Error())
	}
	return i
}

// ReadIntSlice returns an integer slice that has n integers.
func ReadIntSlice(n int) []int {
	b := make([]int, n)
	for i := 0; i < n; i++ {
		b[i] = ReadInt()
	}
	return b
}

// ReadInt64Slice returns as int64 slice that has n integers.
func ReadInt64Slice(n int) []int64 {
	b := make([]int64, n)
	for i := 0; i < n; i++ {
		b[i] = ReadInt64()
	}
	return b
}

// ReadFloat64 returns an float64.
func ReadFloat64() float64 {
	return float64(readFloat64())
}

func readFloat64() float64 {
	f, err := strconv.ParseFloat(ReadString(), 64)
	if err != nil {
		panic(err.Error())
	}
	return f
}

// ReadFloatSlice returns an float64 slice that has n float64.
func ReadFloat64Slice(n int) []float64 {
	b := make([]float64, n)
	for i := 0; i < n; i++ {
		b[i] = ReadFloat64()
	}
	return b
}

// ReadRuneSlice returns a rune slice.
func ReadRuneSlice() []rune {
	return []rune(ReadString())
}

/*********** Debugging ***********/

// ZeroPaddingRuneSlice returns binary expressions of integer n with zero padding.
// For debugging use.
func ZeroPaddingRuneSlice(n, digitsNum int) []rune {
	sn := fmt.Sprintf("%b", n)

	residualLength := digitsNum - len(sn)
	if residualLength <= 0 {
		return []rune(sn)
	}

	zeros := make([]rune, residualLength)
	for i := 0; i < len(zeros); i++ {
		zeros[i] = '0'
	}

	res := []rune{}
	res = append(res, zeros...)
	res = append(res, []rune(sn)...)

	return res
}

// Strtoi is a wrapper of strconv.Atoi().
// If strconv.Atoi() returns an error, Strtoi calls panic.
func Strtoi(s string) int {
	if i, err := strconv.Atoi(s); err != nil {
		panic(errors.New("[argument error]: Strtoi only accepts integer string"))
	} else {
		return i
	}
}

// PrintIntsLine returns integers string delimited by a space.
func PrintIntsLine(A ...int) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.Itoa(A[i])
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// PrintIntsLine returns integers string delimited by a space.
func PrintInts64Line(A ...int64) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.FormatInt(A[i], 10) // 64bit int version
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// PrintfDebug is wrapper of fmt.Fprintf(os.Stderr, format, a...)
func PrintfDebug(format string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, format, a...)
}

// PrintfBufStdout is function for output strings to buffered os.Stdout.
// You may have to call stdout.Flush() finally.
func PrintfBufStdout(format string, a ...interface{}) {
	fmt.Fprintf(stdout, format, a...)
}

/*
URL:
https://codeforces.com/problemset/problem/1324/F
*/

package main

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"math"
	"os"
	"strconv"
)

/********** FAU standard libraries **********/

//fmt.Sprintf("%b\n", 255) 	// binary expression

/********** I/O usage **********/

//str := ReadString()
//i := ReadInt()
//X := ReadIntSlice(n)
//S := ReadRuneSlice()
//a := ReadFloat64()
//A := ReadFloat64Slice(n)

//str := ZeroPaddingRuneSlice(num, 32)
//str := PrintIntsLine(X...)

/*******************************************************************/

const (
	// General purpose
	MOD = 1000000000 + 7
	// MOD          = 998244353
	ALPHABET_NUM = 26
	INF_INT64    = math.MaxInt64
	INF_BIT60    = 1 << 60
	INF_INT32    = math.MaxInt32
	INF_BIT30    = 1 << 30
	NIL          = -1

	// for dijkstra, prim, and so on
	WHITE = 0
	GRAY  = 1
	BLACK = 2
)

func init() {
	// bufio.ScanWords <---> bufio.ScanLines
	ReadString = newReadString(os.Stdin, bufio.ScanWords)
	stdout = bufio.NewWriter(os.Stdout)
}

var (
	n     int
	A     []int
	edges [][]int
)

func main() {
	n = ReadInt()
	A = ReadIntSlice(n)
	for i := 0; i < n-1; i++ {
		x, y := ReadInt2()
		x--
		y--

		e := []int{x, y}
		edges = append(edges, e)
	}

	f := func(l, r T) T {
		res := T(0)
		if l > 0 {
			res += l
		}
		if r > 0 {
			res += r
		}
		return res
	}
	g := func(t T, idx int) T {
		var diff T
		if A[idx] == 0 {
			diff = -1
		} else {
			diff = 1
		}
		return t + diff
	}
	s := NewReRooting(n, edges, 0, f, g)

	ans := []int{}
	for i := 0; i < n; i++ {
		ans = append(ans, int(s.Query(i)))
	}
	fmt.Println(PrintIntsLine(ans...))
}

type T int

type ReRooting struct {
	NodeCount int

	Identity    T
	Operate     func(l, r T) T
	OperateNode func(t T, idx int) T

	Adjacents         [][]int
	IndexForAdjacents [][]int

	Res []T
	DP  [][]T
}

func NewReRooting(
	nodeCount int, edges [][]int, identity T, operate func(l, r T) T, operateNode func(t T, idx int) T,
) *ReRooting {
	s := new(ReRooting)

	s.NodeCount = nodeCount
	s.Identity = identity
	s.Operate = operate
	s.OperateNode = operateNode

	s.Adjacents = make([][]int, nodeCount)
	s.IndexForAdjacents = make([][]int, nodeCount)
	for _, e := range edges {
		s.IndexForAdjacents[e[0]] = append(s.IndexForAdjacents[e[0]], len(s.Adjacents[e[1]]))
		s.IndexForAdjacents[e[1]] = append(s.IndexForAdjacents[e[1]], len(s.Adjacents[e[0]]))
		s.Adjacents[e[0]] = append(s.Adjacents[e[0]], e[1])
		s.Adjacents[e[1]] = append(s.Adjacents[e[1]], e[0])
	}

	s.DP = make([][]T, len(s.Adjacents))
	s.Res = make([]T, len(s.Adjacents))

	for i := 0; i < len(s.Adjacents); i++ {
		s.DP[i] = make([]T, len(s.Adjacents[i]))
	}

	if s.NodeCount > 1 {
		s.Initialize()
	} else {
		s.Res[0] = s.OperateNode(s.Identity, 0)
	}

	return s
}

func (s *ReRooting) Query(node int) T {
	return s.Res[node]
}

func (s *ReRooting) Initialize() {
	parents, order := make([]int, s.NodeCount), make([]int, s.NodeCount)

	// #region InitOrderedTree
	index := 0
	stack := []int{}
	stack = append(stack, 0)
	parents[0] = -1
	for len(stack) > 0 {
		node := stack[len(stack)-1]
		stack = stack[:len(stack)-1]
		order[index] = node
		index++
		for i := 0; i < len(s.Adjacents[node]); i++ {
			adjacent := s.Adjacents[node][i]
			if adjacent == parents[node] {
				continue
			}
			stack = append(stack, adjacent)
			parents[adjacent] = node
		}
	}
	// endregion

	// #region fromLeaf
	for i := len(order) - 1; i >= 1; i-- {
		node := order[i]
		parent := parents[node]

		accum := s.Identity
		parentIndex := -1
		for j := 0; j < len(s.Adjacents[node]); j++ {
			if s.Adjacents[node][j] == parent {
				parentIndex = j
				continue
			}
			accum = s.Operate(accum, s.DP[node][j])
		}
		s.DP[parent][s.IndexForAdjacents[node][parentIndex]] = s.OperateNode(accum, node)
	}
	// endregion

	// #region toLeaf
	for i := 0; i < len(order); i++ {
		node := order[i]
		accum := s.Identity
		accumsFromTail := make([]T, len(s.Adjacents[node]))
		accumsFromTail[len(accumsFromTail)-1] = s.Identity
		for j := len(accumsFromTail) - 1; j >= 1; j-- {
			accumsFromTail[j-1] = s.Operate(s.DP[node][j], accumsFromTail[j])
		}
		for j := 0; j < len(accumsFromTail); j++ {
			s.DP[s.Adjacents[node][j]][s.IndexForAdjacents[node][j]] = s.OperateNode(s.Operate(accum, accumsFromTail[j]), node)
			accum = s.Operate(accum, s.DP[node][j])
		}
		s.Res[node] = s.OperateNode(accum, node)
	}
	// endregion
}

/*******************************************************************/

/*********** I/O ***********/

var (
	// ReadString returns a WORD string.
	ReadString func() string
	stdout     *bufio.Writer
)

func newReadString(ior io.Reader, sf bufio.SplitFunc) func() string {
	r := bufio.NewScanner(ior)
	r.Buffer(make([]byte, 1024), int(1e+9)) // for Codeforces
	r.Split(sf)

	return func() string {
		if !r.Scan() {
			panic("Scan failed")
		}
		return r.Text()
	}
}

// ReadInt returns an integer.
func ReadInt() int {
	return int(readInt64())
}
func ReadInt2() (int, int) {
	return int(readInt64()), int(readInt64())
}
func ReadInt3() (int, int, int) {
	return int(readInt64()), int(readInt64()), int(readInt64())
}
func ReadInt4() (int, int, int, int) {
	return int(readInt64()), int(readInt64()), int(readInt64()), int(readInt64())
}

// ReadInt64 returns as integer as int64.
func ReadInt64() int64 {
	return readInt64()
}
func ReadInt64_2() (int64, int64) {
	return readInt64(), readInt64()
}
func ReadInt64_3() (int64, int64, int64) {
	return readInt64(), readInt64(), readInt64()
}
func ReadInt64_4() (int64, int64, int64, int64) {
	return readInt64(), readInt64(), readInt64(), readInt64()
}

func readInt64() int64 {
	i, err := strconv.ParseInt(ReadString(), 0, 64)
	if err != nil {
		panic(err.Error())
	}
	return i
}

// ReadIntSlice returns an integer slice that has n integers.
func ReadIntSlice(n int) []int {
	b := make([]int, n)
	for i := 0; i < n; i++ {
		b[i] = ReadInt()
	}
	return b
}

// ReadInt64Slice returns as int64 slice that has n integers.
func ReadInt64Slice(n int) []int64 {
	b := make([]int64, n)
	for i := 0; i < n; i++ {
		b[i] = ReadInt64()
	}
	return b
}

// ReadFloat64 returns an float64.
func ReadFloat64() float64 {
	return float64(readFloat64())
}

func readFloat64() float64 {
	f, err := strconv.ParseFloat(ReadString(), 64)
	if err != nil {
		panic(err.Error())
	}
	return f
}

// ReadFloatSlice returns an float64 slice that has n float64.
func ReadFloat64Slice(n int) []float64 {
	b := make([]float64, n)
	for i := 0; i < n; i++ {
		b[i] = ReadFloat64()
	}
	return b
}

// ReadRuneSlice returns a rune slice.
func ReadRuneSlice() []rune {
	return []rune(ReadString())
}

/*********** Debugging ***********/

// ZeroPaddingRuneSlice returns binary expressions of integer n with zero padding.
// For debugging use.
func ZeroPaddingRuneSlice(n, digitsNum int) []rune {
	sn := fmt.Sprintf("%b", n)

	residualLength := digitsNum - len(sn)
	if residualLength <= 0 {
		return []rune(sn)
	}

	zeros := make([]rune, residualLength)
	for i := 0; i < len(zeros); i++ {
		zeros[i] = '0'
	}

	res := []rune{}
	res = append(res, zeros...)
	res = append(res, []rune(sn)...)

	return res
}

// Strtoi is a wrapper of strconv.Atoi().
// If strconv.Atoi() returns an error, Strtoi calls panic.
func Strtoi(s string) int {
	if i, err := strconv.Atoi(s); err != nil {
		panic(errors.New("[argument error]: Strtoi only accepts integer string"))
	} else {
		return i
	}
}

// PrintIntsLine returns integers string delimited by a space.
func PrintIntsLine(A ...int) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.Itoa(A[i])
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// PrintIntsLine returns integers string delimited by a space.
func PrintInts64Line(A ...int64) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.FormatInt(A[i], 10) // 64bit int version
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// PrintfDebug is wrapper of fmt.Fprintf(os.Stderr, format, a...)
func PrintfDebug(format string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, format, a...)
}

// PrintfBufStdout is function for output strings to buffered os.Stdout.
// You may have to call stdout.Flush() finally.
func PrintfBufStdout(format string, a ...interface{}) {
	fmt.Fprintf(stdout, format, a...)
}

package main

import (
	"bufio"
	. "fmt"
	"io"
	"os"
)

// github.com/EndlessCheng/codeforces-go
func CF1324F(_r io.Reader, _w io.Writer) {
	in := bufio.NewReader(_r)
	out := bufio.NewWriter(_w)
	defer out.Flush()
	max := func(a, b int) int {
		if a >= b {
			return a
		}
		return b
	}

	var n, v, w int
	Fscan(in, &n)
	color := make([]int, n)
	for i := range color {
		Fscan(in, &color[i])
		if color[i] == 0 {
			color[i] = -1
		}
	}
	g := make([][]int, n+1)
	for i := 0; i < n-1; i++ {
		Fscan(in, &v, &w)
		g[v] = append(g[v], w)
		g[w] = append(g[w], v)
	}
	g[1] = append(g[1], 0)

	ans := make([]int, n+1)
	var f func(v, fa int) int
	f = func(v, fa int) int {
		sum := color[v-1]
		for _, w := range g[v] {
			if w != fa {
				sum += f(w, v)
			}
		}
		ans[v] = sum
		if sum < 0 {
			return 0
		}
		return sum
	}
	f(1, 0)
	var f2 func(v, fa int)
	f2 = func(v, fa int) {
		if ans[v] >= 0 {
			ans[v] = max(ans[v], ans[fa])
		} else {
			ans[v] = max(ans[v], ans[v]+ans[fa])
		}
		for _, w := range g[v] {
			if w != fa {
				f2(w, v)
			}
		}
	}
	f2(1, 0)
	for _, v := range ans[1:] {
		Fprint(out, v, " ")
	}
}

func main() { CF1324F(os.Stdin, os.Stdout) }

package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

func main() {
	r := bufio.NewReader(os.Stdin)
	var n int
	fmt.Fscan(r, &n)
	a := make([]int, n+1)
	for i := 1; i <= n; i++ {
		fmt.Fscan(r, &a[i])
	}
	g := make([][]int, n+1)
	for i := 0; i < n-1; i++ {
		var u, v int
		fmt.Fscan(r, &u, &v)
		g[u] = append(g[u], v)
		g[v] = append(g[v], u)
	}
	rls := solve(n, a, g)
	fmt.Println(strings.Trim(fmt.Sprint(rls), "[]"))
}

func solve(n int, a []int, g [][]int) []int {
	for i := range a {
		if a[i] == 0 {
			a[i] = -1
		}
	}

	dp := make([]int, n+1)

	var dfs func(v, f int) int
	dfs = func(v, f int) int {
		dp[v] = a[v]
		for _, child := range g[v] {
			if child == f {
				continue
			}
			s := dfs(child, v)
			if s > 0 {
				dp[v] += s
			}
		}
		return dp[v]
	}
	dfs(1, 0)

	var calcu func(v, f int)
	calcu = func(v, f int) {
		if dp[v] > 0 {
			dp[v] = max(dp[v], dp[f])
		} else {
			dp[v] = max(dp[v], dp[v]+dp[f])
		}
		for _, child := range g[v] {
			if child == f {
				continue
			}
			calcu(child, v)
		}
	}
	calcu(1, 0)
	return dp[1:]
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

/*
URL:
https://codeforces.com/problemset/problem/1324/F
*/

package main

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"math"
	"os"
	"strconv"
)

/********** FAU standard libraries **********/

//fmt.Sprintf("%b\n", 255) 	// binary expression

/********** I/O usage **********/

//str := ReadString()
//i := ReadInt()
//X := ReadIntSlice(n)
//S := ReadRuneSlice()
//a := ReadFloat64()
//A := ReadFloat64Slice(n)

//str := ZeroPaddingRuneSlice(num, 32)
//str := PrintIntsLine(X...)

/*******************************************************************/

const (
	// General purpose
	MOD = 1000000000 + 7
	// MOD          = 998244353
	ALPHABET_NUM = 26
	INF_INT64    = math.MaxInt64
	INF_BIT60    = 1 << 60
	INF_INT32    = math.MaxInt32
	INF_BIT30    = 1 << 30
	NIL          = -1

	// for dijkstra, prim, and so on
	WHITE = 0
	GRAY  = 1
	BLACK = 2
)

func init() {
	// bufio.ScanWords <---> bufio.ScanLines
	ReadString = newReadString(os.Stdin, bufio.ScanWords)
	stdout = bufio.NewWriter(os.Stdout)
}

var (
	n int
	A []int

	G       [200000 + 50][]int
	dp      [200000 + 50]int
	answers [200000 + 50]int
)

func main() {
	n = ReadInt()
	A = ReadIntSlice(n)
	for i := 0; i < n-1; i++ {
		a, b := ReadInt2()
		a--
		b--

		G[a] = append(G[a], b)
		G[b] = append(G[b], a)
	}

	dfs1(0, -1)
	PrintfDebug("%v\n", dp[:n])
	dfs2(0, -1, 0)

	fmt.Println(PrintIntsLine(answers[:n]...))
}

func dfs2(cid, pid, dpar int) {
	dchilds := []int{}
	nexts := []int{}
	for _, nid := range G[cid] {
		if nid == pid {
			continue
		}
		dchilds = append(dchilds, dp[nid])
		nexts = append(nexts, nid)
	}

	// cidの答えを計算
	root := 0
	if A[cid] == 0 {
		root--
	} else {
		root++
	}
	other := 0
	for _, v := range dchilds {
		other += Max(v, 0)
	}
	other += Max(dpar, 0)
	answers[cid] = root + other

	l := len(dchilds)
	if l == 0 {
		return
	}
	if l == 1 {
		dfs2(nexts[0], cid, root+Max(dpar, 0))
		return
	}

	// 子が2つ以上の場合
	R, L := make([]int, l), make([]int, l)
	L[0] = Max(dchilds[0], 0)
	for i := 1; i < l; i++ {
		L[i] = L[i-1] + Max(dchilds[i], 0)
	}
	R[l-1] = Max(dchilds[l-1], 0)
	for i := l - 2; i >= 0; i-- {
		R[i] = R[i+1] + Max(dchilds[i], 0)
	}
	for i, nid := range nexts {
		if i == 0 {
			dfs2(nid, cid, Max(root+R[1], 0))
		} else if i == l-1 {
			dfs2(nid, cid, Max(root+L[l-2], 0))
		} else {
			dfs2(nid, cid, Max(root+L[i-1]+R[i+1], 0))
		}
	}
}

func dfs1(cid, pid int) int {
	res := 0
	if A[cid] == 0 {
		res--
	} else {
		res++
	}

	for _, nid := range G[cid] {
		if nid == pid {
			continue
		}
		res += Max(dfs1(nid, cid), 0)
	}

	dp[cid] = res
	return res
}

// Max returns the max integer among input set.
// This function needs at least 1 argument (no argument causes panic).
func Max(integers ...int) int {
	m := integers[0]
	for i, integer := range integers {
		if i == 0 {
			continue
		}
		if m < integer {
			m = integer
		}
	}
	return m
}

/*******************************************************************/

/*********** I/O ***********/

var (
	// ReadString returns a WORD string.
	ReadString func() string
	stdout     *bufio.Writer
)

func newReadString(ior io.Reader, sf bufio.SplitFunc) func() string {
	r := bufio.NewScanner(ior)
	r.Buffer(make([]byte, 1024), int(1e+9)) // for Codeforces
	r.Split(sf)

	return func() string {
		if !r.Scan() {
			panic("Scan failed")
		}
		return r.Text()
	}
}

// ReadInt returns an integer.
func ReadInt() int {
	return int(readInt64())
}
func ReadInt2() (int, int) {
	return int(readInt64()), int(readInt64())
}
func ReadInt3() (int, int, int) {
	return int(readInt64()), int(readInt64()), int(readInt64())
}
func ReadInt4() (int, int, int, int) {
	return int(readInt64()), int(readInt64()), int(readInt64()), int(readInt64())
}

// ReadInt64 returns as integer as int64.
func ReadInt64() int64 {
	return readInt64()
}
func ReadInt64_2() (int64, int64) {
	return readInt64(), readInt64()
}
func ReadInt64_3() (int64, int64, int64) {
	return readInt64(), readInt64(), readInt64()
}
func ReadInt64_4() (int64, int64, int64, int64) {
	return readInt64(), readInt64(), readInt64(), readInt64()
}

func readInt64() int64 {
	i, err := strconv.ParseInt(ReadString(), 0, 64)
	if err != nil {
		panic(err.Error())
	}
	return i
}

// ReadIntSlice returns an integer slice that has n integers.
func ReadIntSlice(n int) []int {
	b := make([]int, n)
	for i := 0; i < n; i++ {
		b[i] = ReadInt()
	}
	return b
}

// ReadInt64Slice returns as int64 slice that has n integers.
func ReadInt64Slice(n int) []int64 {
	b := make([]int64, n)
	for i := 0; i < n; i++ {
		b[i] = ReadInt64()
	}
	return b
}

// ReadFloat64 returns an float64.
func ReadFloat64() float64 {
	return float64(readFloat64())
}

func readFloat64() float64 {
	f, err := strconv.ParseFloat(ReadString(), 64)
	if err != nil {
		panic(err.Error())
	}
	return f
}

// ReadFloatSlice returns an float64 slice that has n float64.
func ReadFloat64Slice(n int) []float64 {
	b := make([]float64, n)
	for i := 0; i < n; i++ {
		b[i] = ReadFloat64()
	}
	return b
}

// ReadRuneSlice returns a rune slice.
func ReadRuneSlice() []rune {
	return []rune(ReadString())
}

/*********** Debugging ***********/

// ZeroPaddingRuneSlice returns binary expressions of integer n with zero padding.
// For debugging use.
func ZeroPaddingRuneSlice(n, digitsNum int) []rune {
	sn := fmt.Sprintf("%b", n)

	residualLength := digitsNum - len(sn)
	if residualLength <= 0 {
		return []rune(sn)
	}

	zeros := make([]rune, residualLength)
	for i := 0; i < len(zeros); i++ {
		zeros[i] = '0'
	}

	res := []rune{}
	res = append(res, zeros...)
	res = append(res, []rune(sn)...)

	return res
}

// Strtoi is a wrapper of strconv.Atoi().
// If strconv.Atoi() returns an error, Strtoi calls panic.
func Strtoi(s string) int {
	if i, err := strconv.Atoi(s); err != nil {
		panic(errors.New("[argument error]: Strtoi only accepts integer string"))
	} else {
		return i
	}
}

// PrintIntsLine returns integers string delimited by a space.
func PrintIntsLine(A ...int) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.Itoa(A[i])
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// PrintIntsLine returns integers string delimited by a space.
func PrintInts64Line(A ...int64) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.FormatInt(A[i], 10) // 64bit int version
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// PrintfDebug is wrapper of fmt.Fprintf(os.Stderr, format, a...)
func PrintfDebug(format string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, format, a...)
}

// PrintfBufStdout is function for output strings to buffered os.Stdout.
// You may have to call stdout.Flush() finally.
func PrintfBufStdout(format string, a ...interface{}) {
	fmt.Fprintf(stdout, format, a...)
}

/*
URL:
https://codeforces.com/problemset/problem/1324/F
*/

package main

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"math"
	"os"
	"strconv"
)

/********** FAU standard libraries **********/

//fmt.Sprintf("%b\n", 255) 	// binary expression

/********** I/O usage **********/

//str := ReadString()
//i := ReadInt()
//X := ReadIntSlice(n)
//S := ReadRuneSlice()
//a := ReadFloat64()
//A := ReadFloat64Slice(n)

//str := ZeroPaddingRuneSlice(num, 32)
//str := PrintIntsLine(X...)

/*******************************************************************/

const (
	// General purpose
	MOD = 1000000000 + 7
	// MOD          = 998244353
	ALPHABET_NUM = 26
	INF_INT64    = math.MaxInt64
	INF_BIT60    = 1 << 60
	INF_INT32    = math.MaxInt32
	INF_BIT30    = 1 << 30
	NIL          = -1

	// for dijkstra, prim, and so on
	WHITE = 0
	GRAY  = 1
	BLACK = 2
)

func init() {
	// bufio.ScanWords <---> bufio.ScanLines
	ReadString = newReadString(os.Stdin, bufio.ScanWords)
	stdout = bufio.NewWriter(os.Stdout)
}

var (
	n int
	A []int

	G       [200000 + 50][]int
	dp      [200000 + 50]int
	answers [200000 + 50]int
)

func main() {
	n = ReadInt()
	A = ReadIntSlice(n)
	for i := 0; i < n-1; i++ {
		a, b := ReadInt2()
		a--
		b--

		G[a] = append(G[a], b)
		G[b] = append(G[b], a)
	}

	dfs1(0, -1)
	PrintfDebug("%v\n", dp[:n])
	dfs2(0, -1, 0)

	fmt.Println(PrintIntsLine(answers[:n]...))
}

func dfs2(cid, pid, dpar int) {
	dchilds := []int{}
	nexts := []int{}
	for _, nid := range G[cid] {
		if nid == pid {
			continue
		}
		dchilds = append(dchilds, dp[nid])
		nexts = append(nexts, nid)
	}

	// cidの答えを計算
	root := 0
	if A[cid] == 0 {
		root--
	} else {
		root++
	}
	other := 0
	for _, v := range dchilds {
		other += Max(v, 0)
	}
	other += Max(dpar, 0)
	// fmt.Println(root + other)
	answers[cid] = root + other

	l := len(dchilds)
	if l == 0 {
		return
	}
	if l == 1 {
		dfs2(nexts[0], cid, root+Max(dpar, 0))
		return
	}

	// 子が2つ以上の場合
	R, L := make([]int, l), make([]int, l)
	L[0] = Max(dchilds[0], 0)
	for i := 1; i < l; i++ {
		L[i] = L[i-1] + Max(dchilds[i], 0)
	}
	R[l-1] = Max(dchilds[l-1], 0)
	for i := l - 2; i >= 0; i-- {
		R[i] = R[i+1] + Max(dchilds[i], 0)
	}
	for i, nid := range nexts {
		if i == 0 {
			dfs2(nid, cid, root+R[1])
		} else if i == l-1 {
			dfs2(nid, cid, root+L[l-2])
		} else {
			dfs2(nid, cid, root+L[i-1]+R[i+1])
		}
	}
}

func dfs1(cid, pid int) int {
	res := 0
	if A[cid] == 0 {
		res--
	} else {
		res++
	}

	for _, nid := range G[cid] {
		if nid == pid {
			continue
		}
		res += Max(dfs1(nid, cid), 0)
	}

	dp[cid] = res
	return res
}

// Max returns the max integer among input set.
// This function needs at least 1 argument (no argument causes panic).
func Max(integers ...int) int {
	m := integers[0]
	for i, integer := range integers {
		if i == 0 {
			continue
		}
		if m < integer {
			m = integer
		}
	}
	return m
}

/*******************************************************************/

/*********** I/O ***********/

var (
	// ReadString returns a WORD string.
	ReadString func() string
	stdout     *bufio.Writer
)

func newReadString(ior io.Reader, sf bufio.SplitFunc) func() string {
	r := bufio.NewScanner(ior)
	r.Buffer(make([]byte, 1024), int(1e+9)) // for Codeforces
	r.Split(sf)

	return func() string {
		if !r.Scan() {
			panic("Scan failed")
		}
		return r.Text()
	}
}

// ReadInt returns an integer.
func ReadInt() int {
	return int(readInt64())
}
func ReadInt2() (int, int) {
	return int(readInt64()), int(readInt64())
}
func ReadInt3() (int, int, int) {
	return int(readInt64()), int(readInt64()), int(readInt64())
}
func ReadInt4() (int, int, int, int) {
	return int(readInt64()), int(readInt64()), int(readInt64()), int(readInt64())
}

// ReadInt64 returns as integer as int64.
func ReadInt64() int64 {
	return readInt64()
}
func ReadInt64_2() (int64, int64) {
	return readInt64(), readInt64()
}
func ReadInt64_3() (int64, int64, int64) {
	return readInt64(), readInt64(), readInt64()
}
func ReadInt64_4() (int64, int64, int64, int64) {
	return readInt64(), readInt64(), readInt64(), readInt64()
}

func readInt64() int64 {
	i, err := strconv.ParseInt(ReadString(), 0, 64)
	if err != nil {
		panic(err.Error())
	}
	return i
}

// ReadIntSlice returns an integer slice that has n integers.
func ReadIntSlice(n int) []int {
	b := make([]int, n)
	for i := 0; i < n; i++ {
		b[i] = ReadInt()
	}
	return b
}

// ReadInt64Slice returns as int64 slice that has n integers.
func ReadInt64Slice(n int) []int64 {
	b := make([]int64, n)
	for i := 0; i < n; i++ {
		b[i] = ReadInt64()
	}
	return b
}

// ReadFloat64 returns an float64.
func ReadFloat64() float64 {
	return float64(readFloat64())
}

func readFloat64() float64 {
	f, err := strconv.ParseFloat(ReadString(), 64)
	if err != nil {
		panic(err.Error())
	}
	return f
}

// ReadFloatSlice returns an float64 slice that has n float64.
func ReadFloat64Slice(n int) []float64 {
	b := make([]float64, n)
	for i := 0; i < n; i++ {
		b[i] = ReadFloat64()
	}
	return b
}

// ReadRuneSlice returns a rune slice.
func ReadRuneSlice() []rune {
	return []rune(ReadString())
}

/*********** Debugging ***********/

// ZeroPaddingRuneSlice returns binary expressions of integer n with zero padding.
// For debugging use.
func ZeroPaddingRuneSlice(n, digitsNum int) []rune {
	sn := fmt.Sprintf("%b", n)

	residualLength := digitsNum - len(sn)
	if residualLength <= 0 {
		return []rune(sn)
	}

	zeros := make([]rune, residualLength)
	for i := 0; i < len(zeros); i++ {
		zeros[i] = '0'
	}

	res := []rune{}
	res = append(res, zeros...)
	res = append(res, []rune(sn)...)

	return res
}

// Strtoi is a wrapper of strconv.Atoi().
// If strconv.Atoi() returns an error, Strtoi calls panic.
func Strtoi(s string) int {
	if i, err := strconv.Atoi(s); err != nil {
		panic(errors.New("[argument error]: Strtoi only accepts integer string"))
	} else {
		return i
	}
}

// PrintIntsLine returns integers string delimited by a space.
func PrintIntsLine(A ...int) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.Itoa(A[i])
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// PrintIntsLine returns integers string delimited by a space.
func PrintInts64Line(A ...int64) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.FormatInt(A[i], 10) // 64bit int version
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// PrintfDebug is wrapper of fmt.Fprintf(os.Stderr, format, a...)
func PrintfDebug(format string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, format, a...)
}

// PrintfBufStdout is function for output strings to buffered os.Stdout.
// You may have to call stdout.Flush() finally.
func PrintfBufStdout(format string, a ...interface{}) {
	fmt.Fprintf(stdout, format, a...)
}