#include <iostream>
#include <utility>
#include <cmath>
#include <algorithm>
#include <string>
#include <set>
#include <queue>
#define MAX_N 5005
#define INF 8000000000000

using namespace std;
typedef long long ll;

int N;
ll A[MAX_N];
vector<int> G[MAX_N];
ll dp[2][MAX_N][MAX_N];//i,v,k 親成分以外が条件を満たす/親成分すべて正　連結成分の数
ll dpn[2][MAX_N];

void show(){
    //debug
    for(int n=0;n<N;n++){
        for(int k=0;k<=N;k++){
            if(dp[0][n][k]==INF){cout<<"INF ";continue;}
            cout<<dp[0][n][k]<<" ";
        }
        cout<<endl;
    }
    cout<<endl;
    for(int n=0;n<N;n++){
        for(int k=0;k<=N;k++){
            if(dp[1][n][k]==INF){cout<<"INF ";continue;}
            cout<<dp[1][n][k]<<" ";
        }
        cout<<endl;
    }
    cout<<"--------------------------------"<<endl;
    
}

int dfs(int p,int n){//親ノード、今のノード
    int count = 0;
    int K_n=1,K_c=0;
    for(int i = 0;i < G[n].size();i++){
        int c = G[n][i];
        if(c==p)continue;
        count++;
        K_c = dfs(n,c);
        if(count==1){
            for(int k = 1;k <= K_n+K_c;k++){
                //nをk個目の独立した連結成分にする場合
                if(dp[0][c][k-1]<0||dp[1][c][k-1]!=INF){
                    dp[0][n][k]=min(dp[0][n][k],A[n]);
                    if(A[n]>0)
                        dp[1][n][k]=min(dp[1][n][k],A[n]);
                }
                //cの連結成分につなげる場合
                if(dp[0][c][k]!=INF)
                    dp[0][n][k]=min(dp[0][n][k],dp[0][c][k]+A[n]);
                if(A[n]>0&&dp[1][c][k]!=INF)
                    dp[1][n][k]=min(dp[1][n][k],dp[1][c][k]+A[n]);
            }
        }else{
            for(int k = 0;k <= K_n+K_c;k++){
                dpn[0][k]=INF;
                dpn[1][k]=INF;
            }
            for(int k_n = 1;k_n <= K_n;k_n++){
                if(dp[0][n][k_n]==INF)continue;
                for(int k_c = 1;k_c <= K_c;k_c++){
                    //cのノードをnに繋げない場合
                    if(dp[0][c][k_c]<0||dp[1][c][k_c]!=INF){//cのノード以下が問題文の条件を満たしていれば、繋がなくても良い。
                        dpn[0][k_c+k_n] = min(dpn[0][k_c+k_n],dp[0][n][k_n]);
                        dpn[1][k_c+k_n] = min(dpn[1][k_c+k_n],dp[1][n][k_n]);
                    }
                    //cをnの連結成分につなげる場合
                    if(dp[0][c][k_c]!=INF){
                        dpn[0][k_c+k_n-1]=min(dpn[0][k_c+k_n-1],dp[0][c][k_c]+dp[0][n][k_n]);
                    }
                    if(dp[1][c][k_c]!=INF&&dp[1][n][k_n]!=INF){
                        dpn[1][k_c+k_n-1]=min(dpn[1][k_c+k_n-1],dp[1][c][k_c]+dp[1][n][k_n]);
                    }
                }
            }
            for(int k = 0;k <= K_n+K_c;k++){
                dp[0][n][k]=dpn[0][k];
                dp[1][n][k]=dpn[1][k];
            }
            
        }
        K_n += K_c;
    }
    if(p>=0&&count==0){
        dp[0][n][1]=A[n];
        if(A[n]>0){
            dp[1][n][1]=A[n];
        }
    }
//    cout<<n<<endl;
//    show();
    return K_n;
}

int main() {
    cin>>N;
    for(int i=0;i<N;i++){
        for(int j=0;j<=N;j++){
            dp[0][i][j]=INF;
            dp[1][i][j]=INF;
        }
        cin>>A[i];
    }
    for(int i=0;i<N-1;i++){
        int a,b;
        cin>>a>>b;
        a--,b--;
        G[a].push_back(b);
        G[b].push_back(a);
    }
    dfs(-1,0);
    int ans;
    
    
    
    for(int k=1;k<=N;k++){
        if(dp[0][0][k]<0){
            cout<<k-1<<endl;
            //            cout<<"debug 1"<<endl;
            return 0;
        }
        if(dp[1][0][k]!=INF&&dp[1][0][k]>0){
            cout<<k-1<<endl;
            //            cout<<"debug 2:"<<dp[1][0][k]<<endl;
            return 0;
        }
    }
}


Measured memory_bytes: 392448