package main

import (
  "bufio"
  "container/list"
  "fmt"
  "os"
  "strconv"
  "strings"
)

const INF32 = 100000000
const INF64 int64 = 1000000000000000000

var n int
var a []int64
var tree [][]int

func main() {
  input := Input{bufio.NewReaderSize(os.Stdin,10000)}
  n = input.NextInt()
  a = input.NextIntArray()
  tree = make([][]int,n)
  for i:=0;i<n-1;i++ {
    u,v := input.NextInts()
    tree[u-1] = append(tree[u-1],v-1)
    tree[v-1] = append(tree[v-1],u-1)
  }
  fmt.Println(solve())
}
func min32(n,m int) int {
  if n < m { return n }
  return m
}
func min64(n,m int64) int64 {
  if n < m { return n }
  return m
}
func fill(a *[]int64,n int64) {
  for i:=0;i<len(*a);i++ { (*a)[i] = n }
}

var order []Node
var dp1 [][]int64
var dp2 [][]int64
var dp3 []int

func solve() int {
  order_from_leaf()
  dp1 = make([][]int64,n)
  dp2 = make([][]int64,n)
  dp3 = make([]int,n)
  for _,node := range order { merge(node) }
  m := INF32
  for i:=0;i<n;i++ {
    if dp1[0][i] != INF64 { m = min32(m,i) }
    if dp2[0][i] < 0 { m = min32(m,i) }
  }
  return m
}
func merge(node Node) {
  id := node.id
  dp1[id] = []int64{INF64}
  dp2[id] = []int64{INF64}
  if a[id] > 0 {
    dp1[id][0] = a[id]
  } else {
    dp2[id][0] = a[id]
  }
  c := 1
  for _,e := range tree[id] {
    if e == node.par { continue }
    tmp1 := make([]int64,c+dp3[e])
    fill(&tmp1,INF64)
    tmp2 := make([]int64,c+dp3[e])
    fill(&tmp2,INF64)
    for i:=0;i<c;i++ {
      for j:=0;j<dp3[e];j++ {
        if dp1[id][i] != INF64 {
          if dp1[e][j] != INF64 {
            tmp1[i+j] = min64(tmp1[i+j],dp1[id][i]+dp1[e][j])
          }
          if dp2[e][j] != INF64 {
            tmp2[i+j] = min64(tmp2[i+j],dp1[id][i]+dp2[e][j])
          }
          if dp1[e][j] != INF64 || dp2[e][j] < 0 {
            tmp1[i+j+1] = min64(tmp1[i+j+1],dp1[id][i])
          }
        }
        if dp2[id][i] != INF64 {
          if dp1[e][j] != INF64 {
            tmp2[i+j] = min64(tmp2[i+j],dp2[id][i]+dp1[e][j])
          }
          if dp2[e][j] != INF64 {
            tmp2[i+j] = min64(tmp2[i+j],dp2[id][i]+dp2[e][j])
          }
          if dp1[e][j] != INF64 || dp2[e][j] < 0 {
            tmp2[i+j+1] = min64(tmp2[i+j+1],dp2[id][i])
          }
        }
      }
    }
    dp1[id] = tmp1
    dp2[id] = tmp2
    c += dp3[e]
  }
  dp3[id] = c
}
func order_from_leaf() {
  order = make([]Node,n)
  q := list.New()
  q.PushBack(Node{-1,0})
  i := n-1
  for q.Len() > 0 {
    p := q.Remove(q.Front()).(Node)
    order[i] = p
    i--
    for _,e := range tree[p.id] {
      if e == p.par { continue }
      q.PushBack(Node{p.id,e})
    }
  }
}

type Node struct { par,id int }

type Input struct { reader *bufio.Reader }
func(i *Input) NextLine() string {
  var buffer []byte
  for {
    line,isPrefix,err := i.reader.ReadLine()
    if err != nil { panic(err) }
    buffer = append(buffer,line...)
    if !isPrefix { break }
  }
  return string(buffer)
}
func(i *Input) NextInt() int {
  x,_ := strconv.Atoi(i.NextLine())
  return x
}
func(i *Input) NextInts() (int,int) {
  s := strings.Fields(i.NextLine())
  x,_ := strconv.Atoi(s[0])
  y,_ := strconv.Atoi(s[1])
  return x,y
}
func(i *Input) NextIntArray() []int64 {
  s := strings.Fields(i.NextLine())
  a := make([]int64,len(s))
  for i:=0;i<len(s);i++ { a[i],_ = strconv.ParseInt(s[i],10,64) }
  return a
}

Measured memory_bytes: 182016