/*
ID: espr1t
TASK: 
KEYWORDS: 
*/

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <string>

using namespace std;
FILE* in = stdin; FILE* out = stdout;

const int MAX = 2002;
const int INF = 1000000001;

struct Answer {
    int ops;
    int lower, upper;
    Answer(int ops_ = -1, int lower_ = -1, int upper_ = -1) :
        ops(ops_), lower(lower_), upper(upper_) {};
};

int n;
int a[MAX];
int cnt[MAX];
bool used[MAX];
vector <int> v[MAX];
vector <int> d[MAX];
Answer dyn[MAX];

int buildGraph(int node) {
    used[node] = true;
    cnt[node] = a[node];
    for (int i = 0; i < (int)v[node].size(); i++) {
        if (!used[v[node][i]]) {
            d[node].push_back(v[node][i]);
            cnt[node] += buildGraph(v[node][i]);
        }
    }
    return cnt[node];
}

void mergeBounds(Answer& ans1, const Answer& ans2) {
    if (ans1.upper <= ans2.lower) {
        // ans1 strictly lower than ans2
        ans1.lower = max(0, ans2.lower - ans1.upper);
        ans1.upper = ans2.upper + ans1.upper;
    } else if (ans2.upper <= ans1.lower) {
        // ans2 strictly lower than ans1
        ans1.lower = max(0, ans1.lower - ans2.upper);
        ans1.upper = ans1.upper + ans2.upper;
    } else if (ans1.lower >= ans2.lower && ans1.upper <= ans2.upper) {
        // ans1 entirely in ans2
        ans1.lower = max(0, ans2.lower - ans1.upper);
        ans1.upper = ans2.upper + ans1.upper;
    } else if (ans2.lower >= ans1.lower && ans2.upper <= ans1.upper) {
        // ans2 entirely in ans1
        ans1.lower = max(0, ans1.lower - ans2.upper);
        ans1.upper = ans1.upper + ans2.upper;
    } else {
        // Just intersecting
        ans1.lower = 0;
        ans1.upper = ans1.upper + ans2.upper;
    }
}

Answer recurse(int node) {
    if (cnt[node] == 0)
        return Answer(0, 0, 0);
    if (dyn[node].ops != -1)
        return dyn[node];
    
    Answer ans(0, 0, 0);
    
    for (int i = 0; i < (int)d[node].size(); i++) {
        Answer cur = recurse(d[node][i]);
        cur.lower += cnt[d[node][i]];
        cur.upper += cnt[d[node][i]];
        ans.ops += cur.ops + cnt[d[node][i]];
//        if (node == 0) {
//            fprintf(stderr, "Going to %d gives: %d [%d, %d]\n", d[node][i], cur.ops + cnt[d[node][i]], cur.lower, cur.upper);
//        }
        mergeBounds(ans, cur);
    }
    
    return dyn[node] = ans;
}

int eval(int origin) {
    memset(dyn, -1, sizeof(dyn));
    Answer ans = recurse(origin);
//    fprintf(stderr, "Answer with origin %d: %d [%d, %d]\n", origin, ans.ops, ans.lower, ans.upper);
    if (ans.lower > 0) return INF;
    if (ans.ops % 2 != 0) return INF;
    return ans.ops / 2;
}

int solve() {
    int ans = INF;
    for (int origin = 0; origin < n; origin++) {
        memset(cnt, 0, sizeof(cnt));
        memset(used, 0, sizeof(used));
        for (int i = 0; i < n; i++)
            d[i].clear();
        buildGraph(origin);
        ans = min(ans, eval(origin));
    }
    return ans >= INF ? -1 : ans;
}

int main(void) {
//	in = fopen("E.in", "rt");
	
	fscanf(in, "%d", &n);
	char buff[MAX];
	fscanf(in, "%s", buff);
	for (int i = 0; i < n; i++)
	    a[i] = buff[i] == '1';
	for (int i = 0; i + 1 < n; i++) {
	    int node1, node2;
	    fscanf(in, "%d %d", &node1, &node2);
	    node1--, node2--;
	    v[node1].push_back(node2);
	    v[node2].push_back(node1);
    }
    
    fprintf(out, "%d\n", solve());
	
	return 0;
}

Measured memory_bytes: 768