#include using namespace std; #define rep(i, a, b) for (int i = (a); i < (b); i++) #define fo(i, n) rep(i, 0, n) #define all(x) std::begin(x), std::end(x) #define sz(x) int((x).size()) #define F first #define S second #define MP make_pair #define PB push_back typedef long long ll; typedef vector vi; typedef pair pii; typedef vector vvi; typedef vector vpii; typedef vector vll; typedef pair pll; typedef vector vvll; typedef vector vpll; typedef vector vd; typedef pair pdd; typedef vector vvd; typedef vector vpdd; const ll mod = 1'000'000'007; struct Mod { ll x; Mod(ll xx = 0) : x(xx) {} Mod operator+(Mod b) { return Mod((x + b.x) % mod); } Mod operator-(Mod b) { return Mod((x - b.x + mod) % mod); } Mod operator*(Mod b) { return Mod((x * b.x) % mod); } }; typedef vector vm; typedef pair pmm; typedef vector vvm; typedef vector vpmm; Mod &operator+=(Mod &a, Mod b) { return a = a + b; } Mod &operator*=(Mod &a, Mod b) { return a = a * b; } Mod &operator-=(Mod &a, Mod b) { return a = a - b; } struct Node { int beauty; vi edges; bool super_dead = false; bool somewhat_dead = false; int dist = -1; int parent = -1; int hyperparent = -1; int weight = 0; bool dead() { return super_dead || somewhat_dead; } }; pmm pdiff(pmm a, pmm b) { return MP(a.F - b.F, a.S - b.S); } vector graph; Mod ans; vpii values_and_positions; vpmm subtree_subsums; pmm root_subsum; pmm prepare_dfs(int node, int parent, int dist, int hyperparent) { if (graph[node].super_dead) return MP(Mod(0), Mod(0)); values_and_positions.PB(MP(graph[node].beauty, node)); graph[node].somewhat_dead = false; graph[node].dist = dist; graph[node].parent = parent; graph[node].hyperparent = hyperparent; pmm res = MP(Mod(1), Mod(0)); fo(i, sz(graph[node].edges)) { int v = graph[node].edges[i]; if (v == parent) continue; pmm par_res = prepare_dfs(v, node, dist + 1, hyperparent == -1 ? i : hyperparent); res.F += par_res.F; res.S += par_res.S + par_res.F; if (parent == -1) subtree_subsums.PB(MP(par_res.F, par_res.F + par_res.S)); } return res; } pmm pick(int node) { if (graph[node].dead()) return MP(Mod(0), Mod(0)); graph[node].somewhat_dead = true; pmm res = MP(Mod(1), Mod(0)); for (int v : graph[node].edges) { if (v == graph[node].parent) continue; pmm par_res = pick(node); res.F += par_res.F; res.S += par_res.S + par_res.F; } return res; } void with_centroid(int root) { values_and_positions.clear(); subtree_subsums.clear(); root_subsum = prepare_dfs(root, -1, 0, -1); sort(all(values_and_positions), greater{}); for (auto [val, pos] : values_and_positions) { if (graph[pos].dead()) continue; pmm res = pick(pos); pmm tree_subsum = MP(res.F, res.S + res.F * graph[pos].dist); int hyperparent = graph[pos].hyperparent; if (hyperparent == -1) { fo(i, sz(subtree_subsums)) { pmm subsum = pdiff(root_subsum, subtree_subsums[i]); Mod subans = (subsum.F * subtree_subsums[i].S + subsum.S * subtree_subsums[i].F) * val; ans += subans; root_subsum = pdiff(root_subsum, subtree_subsums[i]); } return; } else { pmm subsum = pdiff(root_subsum, subtree_subsums[hyperparent]); Mod subans = (subsum.F * tree_subsum.S + subsum.S * tree_subsum.F) * val; ans += subans; root_subsum = pdiff(root_subsum, tree_subsum); subtree_subsums[hyperparent] = pdiff(subtree_subsums[hyperparent], tree_subsum); } } } int get_weight(int node, int parent = -1) { if (graph[node].super_dead) return 0; int weight = 1; for (int v : graph[node].edges) { if (v == parent) continue; weight += get_weight(v, node); } return graph[node].weight = weight; } void centroid(int sample) { ll total_nodes = get_weight(sample); ll root = sample; ll parent = -1; while (true) { bool moved = false; for (int v : graph[root].edges) { if (v == parent) continue; if (graph[v].super_dead) continue; if (graph[v].weight * 2 >= total_nodes) { parent = root; root = v; moved = true; break; } } if (!moved) break; } with_centroid(root); graph[root].super_dead = true; for (int v : graph[root].edges) { if (graph[v].super_dead) continue; centroid(v); } } signed main() { cin.tie(0)->sync_with_stdio(0); cin.exceptions(cin.badbit | cin.failbit); int n; cin >> n; graph = vector(n); ans = 0; for (Node &nd : graph) cin >> nd.beauty; fo(i, n - 1) { int a, b; cin >> a >> b; a--; b--; graph[a].edges.PB(b); graph[b].edges.PB(a); } centroid(0); cout << ans.x << endl; }