#include <bits/stdc++.h>
using namespace std;
class tree {
  int ct;

 public:
  int nn, root;
  vector<int> parent;
  vector<int> depth;
  vector<int> sz;
  vector<vector<int>> adj;
  vector<vector<int>> sons;
  vector<int> in, out;
  vector<int> pos;
  vector<vector<int>> pred;
  int MAXLEVEL;
  tree(int n) {
    nn = n;
    adj.clear();
    adj.resize(n);
  }
  void add_path(int a, int b) {
    adj[a].push_back(b);
    adj[b].push_back(a);
  }
  void add_directed_path(int a, int b) { adj[a].push_back(b); }
  void dfs_set_root(int id, bool cartesian_decomposition = false) {
    if (cartesian_decomposition) {
      in[id] = ct;
      pos[ct] = id;
      ct++;
    }
    sz[id]++;
    for (auto p : adj[id]) {
      if (parent[p] == -1) {
        parent[p] = id;
        depth[p] = depth[id] + 1;
        dfs_set_root(p, cartesian_decomposition);
        sz[id] += sz[p];
        sons[id].push_back(p);
      }
    }
    if (cartesian_decomposition) out[id] = ct - 1;
  }
  void set_root(int id, bool cartesian_decomposition = false) {
    if (cartesian_decomposition) {
      in.resize(nn);
      out.resize(nn);
      pos.resize(nn);
      ct = 0;
    }
    parent.assign(nn, -1);
    depth.assign(nn, -1);
    sz.assign(nn, 0);
    sons.clear();
    sons.resize(nn);
    stack<pair<int, int>> st;
    st.push({id, 0});
    parent[id] = 0;
    depth[id] = 0;
    int ct = 0;
    while (!st.empty()) {
      int id = st.top().first, x = st.top().second;
      if (x == 0) {
        in[id] = ct;
        pos[ct] = id;
        ct++;
      }
      if (x >= adj[id].size()) {
        out[id] = ct - 1;
        if (parent[id] != -1) {
          sz[parent[id]] += sz[id];
        }
        st.pop();
      } else {
        st.top().second++;
        int p = adj[id][x];
        if (parent[p] == -1) {
          parent[p] = id;
          depth[p] = depth[id] + 1;
          sz[p] = 1;
          sons[id].push_back(p);
          st.push({p, 0});
        }
      }
    }
    int i = 0;
  }
  void prep_LCA() {
    MAXLEVEL = 1;
    while ((1 << MAXLEVEL) < nn) MAXLEVEL++;
    MAXLEVEL++;
    pred.assign(MAXLEVEL, vector<int>(nn, 0));
    pred[0] = parent;
    int i, j, k;
    for (i = 1; i < MAXLEVEL; i++) {
      for (j = 0; j < nn; j++) {
        if (pred[i - 1][j] != -1) pred[i][j] = pred[i - 1][pred[i - 1][j]];
      }
    }
  }
  int get_p_ancestor(int a, int p) {
    int i;
    for (i = MAXLEVEL - 1; (i >= 0) && (p > 0) && (a != -1); i--) {
      if ((1 << i) & p) {
        p -= (1 << i);
        a = pred[i][a];
      }
    }
    return a;
  }
  int LCA(int a, int b) {
    int da = depth[a], db = depth[b];
    if (da > db) {
      swap(da, db);
      swap(a, b);
    }
    int i, j, k;
    for (i = MAXLEVEL - 1; i >= 0; i--) {
      if (db - (1 << i) >= da) {
        db -= (1 << i);
        b = pred[i][b];
      }
    }
    if (a == b) return a;
    for (i = MAXLEVEL - 1; i >= 0; i--) {
      if (pred[i][a] != pred[i][b]) {
        a = pred[i][a];
        b = pred[i][b];
      }
    }
    return parent[a];
  }
  int get_distance(int a, int b) {
    int c = LCA(a, b);
    int ans = depth[a] + depth[b] - 2 * depth[c];
    return ans;
  }
  int get_diameter() {
    int a, b, c, i, j, k, id, INF = nn + 100, ans;
    vector<int> dist(nn), last(nn);
    queue<int> q;
    if (nn == 1) return 0;
    a = 1;
    dist.assign(nn, INF);
    dist[a] = 0;
    q.push(a);
    while (!q.empty()) {
      id = q.front();
      q.pop();
      for (auto p : adj[id]) {
        if (dist[p] == INF) {
          dist[p] = dist[id] + 1;
          q.push(p);
        }
      }
    }
    a = id;
    dist.assign(nn, INF);
    last.assign(nn, -1);
    dist[a] = 0;
    q.push(a);
    while (!q.empty()) {
      id = q.front();
      q.pop();
      for (auto p : adj[id]) {
        if (dist[p] == INF) {
          dist[p] = dist[id] + 1;
          last[p] = id;
          q.push(p);
        }
      }
    }
    ans = dist[id];
    return ans;
    vector<int> path;
    b = id;
    c = id;
    do {
      path.push_back(b);
      b = last[b];
    } while (b != -1);
    return ans;
  }
};
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int n, i, j, k, a, b, ans, x, l, r, ct, ct2, y;
  cin >> n;
  n++;
  vector<int> c(n), s(n), s2(n);
  for (i = 1; i < n; i++) cin >> c[i];
  tree tr(n);
  tr.add_path(0, 1);
  for (i = 0; i < n - 2; i++) {
    cin >> a >> b;
    tr.add_path(a, b);
  }
  tr.set_root(0, true);
  s[0] = 0;
  s2[0] = 0;
  ct = 0;
  ct2 = 0;
  for (i = 1; i < n; i++) {
    x = tr.pos[i];
    s[i] = s[i - 1];
    s2[i] = s2[i - 1];
    if (c[x] == 1)
      s[i]++, ct++;
    else if (c[x] == 2)
      s2[i]++, ct2++;
  }
  ans = 0;
  for (i = 2; i < n; i++) {
    l = tr.in[i];
    r = tr.out[i];
    x = s[r] - s[l - 1];
    y = s2[r] - s2[l - 1];
    if ((x == 0) && (y == ct2))
      ans++;
    else if ((x == ct) && (y == 0))
      ans++;
  }
  cout << ans << "\n";
  return 0;
}
