#include <bits/stdc++.h>
using namespace std;
/*
so we did get that every child's edges are basically forced, and so every edge is forced
but intsead of calculating this edge and having only (i, child) in state
we make another dimension: (i, current, child)
or rather in the imple: (u, parent, current)
so we don't need to do the case work...
*/
#define int long long
constexpr int INF = 1e9+10;
vector<int> parent, order;
vector<vector<int>> adj;
int n;
int root = 1;
void dfs_parent(int u, int p = -1) {
for (int v : adj[u]) {
if (v == p) continue;
parent[v] = u;
dfs_parent(v, u);
}
order.push_back(u);
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >>n;
adj.resize(n + 1);
for (int i = 0; i < n - 1; i++) {
int a, b; cin >> a >> b;
adj[a].push_back(b);
adj[b].push_back(a);
}
vector<int> A(n + 1);
for (int i = 1; i <= n; i++) cin >> A[i];
parent.resize(n + 1, -1);
dfs_parent(root);
// minimum in the subtree if the parent(u) pressed a and u pressed b
vector<array<array<int, 2>, 2>> dp(n+ 1);
for (int i = 1; i <= n; i++)
for (int a = 0; a < 2; a++)
for (int b = 0; b < 2; b++)
dp[i][a][b] = INF;
for (int u : order) {
for (int P = 0; P <= 1; P++) { // the one that parent(u) pressed
for (int X = 0; X <= 1; X++) { // the one that u pressed
int best[2] = {0, INF};
for (int v : adj[u]) {
if (v == parent[u]) continue;
int c0 = dp[v][X][0];
int c1= dp[v][X][1];
int next0 = min(best[0] + c0, best[1] + c1);
int next1 = min(best[0] + c1, best[1] + c0);
best[0] = next0;
best[1] = next1;
}
// if A[u] == 1, then X ^ P must be 1
// if A[u] == 0, then X ^ P must be 0
// so required: A[u] ^ X ^ P
int need = (A[u] ^ X ^ P);
int childrenCost = best[need];
if (childrenCost >= INF) {
dp[u][P][X] = INF;
} else {
dp[u][P][X] = childrenCost + X;
}
}
}
}
int ans = min(dp[root][0][0], dp[root][0][1]);
if (ans >= INF) cout << "impossible\n";
else cout << ans << "\n";
}