// ---------- begin Tree DP ----------
struct TreeDP<Edge, Value, Init, Merge> {
    size: usize,
    graph: Vec<Vec<(usize, Edge)>>,
    init: Init,
    merge: Merge,
    phantom: std::marker::PhantomData<Value>,
}

impl<Edge, Value, Init, Merge> TreeDP<Edge, Value, Init, Merge>
where Edge: Clone,
      Value: Clone,
      Init: Fn(usize) -> Value,
      Merge: Fn(Value, Value, &Edge) -> Value,
{
    fn new(size: usize, init: Init, merge: Merge) -> Self {
        TreeDP {
            size: size,
            graph: vec![vec![]; size],
            init: init,
            merge: merge,
            phantom: std::marker::PhantomData,
        }
    }
    fn add_edge(&mut self, a: usize, b: usize, c: Edge) {
        assert!(a < self.size && b < self.size && a != b);
        self.graph[a].push((b, c.clone()));
        self.graph[b].push((a, c));
    }
    fn solve(&self, root: usize) -> Value {
        let size = self.size;
        let graph = &self.graph;
        let mut topo = vec![];
        let mut parent = vec![root; size];
        let mut stack = vec![root];
        while let Some(v) = stack.pop() {
            topo.push(v);
            for e in graph[v].iter() {
                if e.0 != parent[v] {
                    parent[e.0] = v;
                    stack.push(e.0);
                }
            }
        }
        assert!(topo.len() == size);
        let mut dp: Vec<Option<Value>> = (0..size).map(|_| None).collect();
        for &v in topo.iter().rev() {
            let mut now = (self.init)(v);
            for u in graph[v].iter() {
                if u.0 == parent[v] {
                    continue;
                }
                let b = dp[u.0].take().unwrap();
                now = (self.merge)(now, b, &u.1);
            }
            dp[v] = Some(now);
        }
        dp[root].take().unwrap()
    }
}
// ---------- end Tree DP ----------
//https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8 より
macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
    ($($r:tt)*) => {
        let s = {
            use std::io::Read;
            let mut s = String::new();
            std::io::stdin().read_to_string(&mut s).unwrap();
            s
        };
        let mut iter = s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
}

macro_rules! input_inner {
    ($iter:expr) => {};
    ($iter:expr, ) => {};
    ($iter:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($iter, $t);
        input_inner!{$iter $($r)*}
    };
}

macro_rules! read_value {
    ($iter:expr, ( $($t:tt),* )) => {
        ( $(read_value!($iter, $t)),* )
    };
    ($iter:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()
    };
    ($iter:expr, chars) => {
        read_value!($iter, String).chars().collect::<Vec<char>>()
    };
    ($iter:expr, usize1) => {
        read_value!($iter, usize) - 1
    };
    ($iter:expr, $t:ty) => {
        $iter.next().unwrap().parse::<$t>().expect("Parse error")
    };
}

//

use std::cmp::min;

fn run() {
    input! {
        n: usize,
        a: [i64; n],
        e: [(usize1, usize1); n - 1],
    }
    type Value = Vec<(i64, i64)>;// バッテリーのみ、コンピュータあり、のmin
    type Edge = ();
    let inf = 1_000_000_000i64 * 5000 + 1;
    let init = |v: usize| -> Value {
        if a[v] > 0 {
            vec![(a[v], a[v])]
        } else {
            vec![(2 * inf, a[v])]
        }
    };
    let merge = |a: Value, b: Value, _c: &Edge| -> Value {
        let mut res = vec![(inf, inf); a.len() + b.len()];
        for (i, a) in a.iter().enumerate() {
            for (j, b) in b.iter().enumerate() {
                // 切らない
                {
                    let p = &mut res[i + j];
                    p.1 = min(p.1, min(a.0, a.1) + min(b.0, b.1));
                    p.0 = min(p.0, a.0 + b.0);
                }
                // 切る
                {
                    let p = &mut res[i + j + 1];
                    if b.1 < 0 {
                        p.0 = min(p.0, a.0);
                        p.1 = min(p.1, a.1);
                    }
                    if b.0 < inf {
                        p.0 = min(p.0, a.0);
                        p.1 = min(p.1, a.1);
                    }
                }
            }
        }
        res
    };
    let mut solver = TreeDP::new(n, init, merge);
    for (a, b) in e {
        solver.add_edge(a, b, ());
    }
    let dp = solver.solve(0);
    let mut ans = 0;
    while dp[ans].0 >= inf && dp[ans].1 >= 0 {
        ans += 1;
    }
    println!("{}", ans);
}

fn main() {
    run();
}


Measured memory_bytes: 6396