// #define _GLIBCXX_DEBUG // for STL debug (optional)
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <string>
#include <cstring>
#include <deque>
#include <list>
#include <queue>
#include <stack>
#include <vector>
#include <utility>
#include <algorithm>
#include <map>
#include <set>
#include <complex>
#include <cmath>
#include <limits>
#include <cfloat>
#include <climits>
#include <ctime>
#include <cassert>
#include <numeric>
#include <fstream>
#include <functional>
#include <bitset>
using namespace std;

#define debug(...) fprintf(stderr, __VA_ARGS__)
#define int long long int
 
template<typename T> void chmax(T &a, T b) {a = max(a, b);}
template<typename T> void chmin(T &a, T b) {a = min(a, b);}
template<typename T> void chadd(T &a, T b) {a = a + b;}
 
typedef pair<int, int> pii;
typedef long long ll;
 
int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};
const ll INF = 1001001001001001LL;
const ll MOD = 1000000007LL;

int N, A[5010], sz[5010], dp[5010][5010][2], tmp[2][5010][2];
vector<int> G[5010];

void dfs(int cur, int par=-1) {
    sz[cur] = 1;
    for(int to : G[cur]) {
        if(to == par) continue;
        dfs(to, cur);
        sz[cur] += sz[to];
    }
}

void solve(int cur, int par=-1) {
    int cnt = 0;
    for(auto to : G[cur]) {
        if(to == par) continue;
        solve(to, cur);
        cnt++;
    }
    
    // cur を根とする部分木には sz[cur] 個のノードがある
    // こたえは sz[cur] - 1 個以下にしかならない
    for(int i=0; i<=sz[cur]; i++) {
        for(int k=0; k<2; k++) {
            tmp[k][i][0] = INF;
            tmp[k][i][1] = false;
        }
    }

    // (偶奇, 総和, mode)
    tmp[0][0][0] = A[cur];
    tmp[0][0][1] = (A[cur] > 0);
    int pari = 0, sum = 0;
    
    for(int to : G[cur]) {
        if(to == par) continue;
        int now = pari, nxt = 1 - pari;
        pari = 1 - pari;
        for(int i=sum; i>=0; i--) {
            
            // 合計は sz[cur]-1 以下
            for(int j=sz[to]-1; j>=0; j--) {
                // 0: その回数を満たす中で総和が最小のもの
                // j 回切った component とつなげるとき
                // fprintf(stderr, "nxt = %lld, i+j = %lld\n", nxt, i+j);
                if(tmp[now][i][0] != INF) {
                    // fprintf(stderr, "tmp[now][%lld][0] = %lld, dp[%lld][%lld][0] = %lld\n", i, tmp[now][i][0], to, j, dp[to][j][0]);
                    chmin(tmp[nxt][i+j][0], tmp[now][i][0] + dp[to][j][0]);
                }
                else {
                    // fprintf(stderr, "i = %lld, j = %lld, tmp[%lld][%lld][0] = INF\n", i, j, now, i);
                }
                
                // j 回切った component とつなげないとき
                // 0: dp[to][j][0] が負のときのみ可能
                // 1: dp[to][j][1] が true のときのみ可能
                if(i+j+1 <= sz[cur]-1) {
                    if(dp[to][j][0] < 0) {
                        chmin(tmp[nxt][i+j+1][0], tmp[now][i][0]);
                    }
                    if(dp[to][j][1] == true) {
                        chmin(tmp[nxt][i+j+1][0], tmp[now][i][0]);
                    }
                }
                
                // 1: その回数を満たして全部正にできる？
                // 正の component とつなげるとき
                tmp[nxt][i+j][1] |= tmp[now][i][1] & dp[to][j][1];

                // 正の component とつなげないとき
                // 0: dp[to][j][0] が負のときのみ可能
                // 1: to[to][j][1] が true のときのみ可能
                if(i+j+1 <= sz[cur]-1) {
                    if(dp[to][j][0] < 0 or dp[to][j][1] == true) {
                        tmp[nxt][i+j+1][1] |= tmp[now][i][1];
                    }
                }
            }
        }
        sum += sz[to];
        for(int i=0; i<=sum; i++) {
            tmp[now][i][0] = INF;
            tmp[now][i][1] = false;
        }        
    }

    for(int i=0; i<sz[cur]; i++) {
        dp[cur][i][0] = tmp[cnt%2][i][0];
        dp[cur][i][1] = tmp[cnt%2][i][1];
    }
    /*
    fprintf(stderr, "# debug: cur = %lld (size = %lld)\n", cur, sz[cur]);
    fprintf(stderr, "zro:");
    for(int i=0; i<sz[cur]; i++) {
        fprintf(stderr, " %lld", dp[cur][i][0]);
    }
    fprintf(stderr, "\n");
    fprintf(stderr, "one:");
    for(int i=0; i<sz[cur]; i++) {
        fprintf(stderr, " %lld", dp[cur][i][1]);
    }
    fprintf(stderr, "\n");
    */
}

signed main() {
    cin >> N;
    for(int i=0; i<N; i++) {
        for(int j=0; j<N; j++) {
            // 最小値なので
            dp[i][j][0] = INF;
        }
    }
    
    for(int i=0; i<N; i++) {
        cin >> A[i];
    }
    for(int i=0; i<N-1; i++) {
        int u, v; cin >> u >> v;
        u--; v--;
        G[u].push_back(v);
        G[v].push_back(u);
    }

    dfs(0);
    solve(0);
    int ans = INF;
    for(int i=0; i<=N; i++) {
        if(dp[0][i][0] < 0) ans = min(ans, i);
        if(dp[0][i][1] == true) ans = min(ans, i);
    }
    cout << ans << endl;
    return 0;
}


Measured memory_bytes: 392832