#include <stdio.h>
#include <assert.h>
#include <fstream>
#include <iostream>
#include <algorithm>
#include <array>
#include <vector>
#include <queue>
#include <set>
#include <cmath>
#include <iomanip>
//#include <unordered_map>
//#include <unordered_set>
//#include <boost/container/static_vector.hpp>
//#include <boost/unordered_set.hpp>
//#include <boost/unordered_map.hpp>
//#include <unistd.h>

class Tree {
    public:
    struct Node {
        std::vector<int> edge;
        int rank;
        int child_bond_num;
        int direction;
    };
    std::vector<Node> node;
    Tree() {}
    Tree(const int node_num_max) {
        node.resize(node_num_max);
    }
    void add_directed_edge(const int from, const int to) {
        node[from].edge.push_back(to);
    }
    void add_undirected_edge(const int node1, const int node2) {
        add_directed_edge(node1, node2);
        add_directed_edge(node2, node1);
    }
    void set_rank(int n, int rank, int parent) { // 辺が有向でも無向でも使える。呼び出すとき、parentは-1にしておくとよい。
        node[n].rank = rank;
        for (int c : node[n].edge) {
            if (c != parent) {
                set_rank(c, rank + 1, n);
            }
        }
    }
    int calc_diameter(int max_idx) {
        // 点は1～max_idxという想定。
        set_rank(1, 0, -1);
        int tmp_idx = 1;
        int tmp_diameter = 0;
        for (int i = 1; i <= max_idx; i++) {
            if (tmp_diameter < node[i].rank) {
                tmp_idx = i;
                tmp_diameter = node[i].rank;
            }
        }
        set_rank(tmp_idx, 0, -1);
        for (int i = 1; i <= max_idx; i++) {
            tmp_diameter = std::max(tmp_diameter, node[i].rank);
        }
        return tmp_diameter;
    }
};

const int MAX_N = 5050;
int N, U[MAX_N], V[MAX_N];
long long A[MAX_N];

Tree tree = Tree(MAX_N);

long long dp_pos[MAX_N][MAX_N], dp_neg[MAX_N][MAX_N];
long long MAX_V = (long long)1000000000 * 10000;

long long dp_pos_tmp[MAX_N][MAX_N], dp_neg_tmp[MAX_N][MAX_N];

void merge(int n) {
    int child[MAX_N];
    int child_num = 0;
    for (int i = 0; i < tree.node[n].edge.size(); i++) {
        int c = tree.node[n].edge[i];
        if (tree.node[c].rank > tree.node[n].rank) {
            child[child_num+1] = c;
            child_num++;
        }
    }

    dp_pos_tmp[0][0] = 0 < A[n] ? A[n] : MAX_V;
    dp_neg_tmp[0][0] = A[n];

    tree.node[n].child_bond_num = 0;
    for (int i = 1; i <= child_num; i++) {
        int c = child[i];

        for (int j = 0; j <= tree.node[n].child_bond_num + tree.node[c].child_bond_num + 1; j++) {
            dp_pos_tmp[i][j] = MAX_V;
            dp_neg_tmp[i][j] = MAX_V;
        }

        for (int j = 0; j <= tree.node[n].child_bond_num; j++) {
            for (int k = 0; k <= tree.node[c].child_bond_num; k++) {
                //if (n == 4) {
                //    std::cout << "check_s:" << i << " " << j << " " << k << " " << dp_neg_tmp[i][1] << " " << dp_neg_tmp[i-1][j] << " " << dp_pos[c][k] << " " << dp_neg[c][k] << std::endl;
                //}
                if (dp_neg_tmp[i-1][j] < MAX_V && (dp_neg[c][k] < 0 || dp_pos[c][k] < MAX_V)) {
                    dp_neg_tmp[i][j+k+1] = std::min(dp_neg_tmp[i][j+k+1], dp_neg_tmp[i-1][j]);
                }
                if (dp_neg_tmp[i-1][j] < MAX_V && dp_pos[c][k] < MAX_V) {
                    dp_neg_tmp[i][j+k] = std::min(dp_neg_tmp[i][j+k], dp_neg_tmp[i-1][j] + dp_pos[c][k]);
                }
                if (dp_neg_tmp[i-1][j] < MAX_V && dp_neg[c][k] < MAX_V) {
                    dp_neg_tmp[i][j+k] = std::min(dp_neg_tmp[i][j+k], dp_neg_tmp[i-1][j] + dp_neg[c][k]);
                }
                if (0 < A[n]) {
                    dp_pos_tmp[i][j+k] = std::min(dp_pos_tmp[i][j+k], dp_pos_tmp[i-1][j] + dp_pos[c][k]);
                    if (dp_pos[c][k] < MAX_V || dp_neg[c][k] < 0) {
                        dp_pos_tmp[i][j+k+1] = std::min(dp_pos_tmp[i][j+k+1], dp_pos_tmp[i-1][j]);
                    }
                }

                //if (n == 4) {
                //    std::cout << "check_e:" << i << " " << j << " " << k << " " << dp_neg_tmp[i][1] << " " << dp_neg_tmp[i-1][j] << " " << dp_pos[c][k] << " " << dp_neg[c][k] << std::endl;
                //}

            }
        }
        tree.node[n].child_bond_num += 1 + tree.node[c].child_bond_num;

        //for (int j = 0; j <= tree.node[n].child_bond_num; j++) {
        //    std::cout << n << " " << i << " " << j << " " << dp_pos_tmp[i][j] << " " << dp_neg_tmp[i][j] << std::endl;
        //}

    }

    for (int j = 0; j <= tree.node[n].child_bond_num; j++) {
        dp_pos[n][j] = dp_pos_tmp[child_num][j];
        dp_neg[n][j] = dp_neg_tmp[child_num][j];
    }

    //for (int i = 0; i <= tree.node[n].child_bond_num; i++) {
    //    std::cout << n << " " << i << " " << dp_pos[n][i] << " " << dp_neg[n][i] << std::endl;
    //}

}

int main(int argc, char **argv) {
    std::cin >> N;
    
    for (int i = 1; i <= N; i++) {
        std::cin >> A[i];
    }

    for (int i = 1; i <= N - 1; i++) {
        std::cin >> U[i] >> V[i];
    }

    for (int i = 1; i <= N - 1; i++) {
        tree.add_undirected_edge(U[i], V[i]);
    }

    tree.set_rank(1, 0, -1);

    std::vector<int> nodes;
    for (int i = 1; i <= N; i++) {
        nodes.push_back(i);
    }

    std::sort(nodes.begin(), nodes.end(),
        [](const int a, const int b) { return tree.node[a].rank > tree.node[b].rank; }
    );

    for (int n : nodes) {
        merge(n);
        //if (n == 4) {
        //    break;
        //}
    }

    int ret = N;
    for (int i = 0; i <= N; i++) {
        if (dp_pos[1][i] < MAX_V || dp_neg[1][i] < 0) {
            ret = std::min(ret, i);
        }
    }

    std::cout << ret << std::endl;


    return 0;
}

Measured memory_bytes: 795776