#include using namespace std; constexpr long long mod = 1e9+7; struct UnionFind{ vector data, max; UnionFind(int size) : data(size, -1), max(size, 0){ for (int i = 0; i < size; ++i) max[i] = i; } void unite(int x, int y){ x = root(x); y = root(y); if (x != y){ if (data[y] < data[x]) swap(x, y); data[x] += data[y]; data[y] = x; } if (max[x] > max[y]){ max[y] = max[x]; }else{ max[x] = max[y]; } } int root(int x) {return data[x] < 0 ? x : data[x] = root(data[x]);} int size(int x) {return -data[root(x)];} int head(int x) {return max[root(x)];} }; void dfs(int v, vector & depth, const vector> &Fs){ for (auto u: Fs[v]){ depth[u] = depth[v] + 1; dfs(u, depth, Fs); } } int main(){ cin.tie(0); ios::sync_with_stdio(false); int N; cin >> N; vector rs(N, 0LL); for (auto & r: rs) cin >> r; vector> Es(N, vector()); for (int i = 1; i < N; ++i){ int a, b; cin >> a >> b; Es[a-1].push_back(b-1); Es[b-1].push_back(a-1); } vector> Fs(N, vector()); UnionFind uf(N); for (int v = 0; v < N; ++v){ for (auto u: Es[v]){ if (u < v){ Fs[v].push_back(uf.head(u)); uf.unite(u, v); } } } vector depth(N, 0); dfs(N-1, depth, Fs); long long ans = 1LL; for (int i = 0; i < N; ++i){ ans *= (1 + depth[i] + rs[i]) % mod; ans %= mod; } cout << ans << endl; return 0; }