#include // iostream is too mainstream #include // bitch please #include #include #include #include #include #include #include #include #include #include #include #include #define dibs reserve #define OVER9000 1234567890 #define ALL_THE(CAKE,LIE) for(auto LIE =CAKE.begin(); LIE != CAKE.end(); LIE++) #define tisic 47 #define soclose 1e-8 #define chocolate win // so much chocolate #define patkan 9 #define ff first #define ss second #define abs(x) ((x < 0)?-(x):x) #define uint unsigned int #define dbl long double #define pi 3.14159265358979323846 using namespace std; // mylittledoge #ifdef DONLINE_JUDGE // palindromic tree is better than splay tree! #define lld I64d #endif typedef long long ll; vector< vector > G; vector par, val; vector ans, ans_inv; ll mod =1000000007; vector< vector< pair > > paths_son(100000); struct fin{ vector T; vector vis; void resize(int N) {clear(); T.resize(N+tisic,0);} int lastone(int x) {return x&(x^(x-1));} void put(int pos, ll val) { val %=mod; for(int i =pos+1; i < (int)T.size(); i +=lastone(i)) { T[i] +=val; vis.push_back(i);} } ll get(int pos) { ll ret =0; for(int i =pos+1; i > 0; i -=lastone(i)) ret +=T[i]; return ret%mod;} void clear() { ALL_THE(vis,it) T[*it] =0; vis.clear();} }; ll pw(ll a, ll e, ll mod) { if(e <= 0) return 1; ll x =pw(a,e/2,mod); x =(x*x)%mod; if(x < 0) x +=mod; if(e%2 != 0) x =(x*a)%mod; if(x < 0) x +=mod; return x;} ll inv(ll a) { a %=mod; if(a == 0) return 0; return pw(a,mod-2,mod);} void DFS_brute(int R, int cur_sum, ll cur_ways, vector< pair > &paths) { ll prod =1, prod_zero =0; ALL_THE(G[R],it) if(*it != par[R]) { if(ans[*it] == 0) prod_zero++; else prod =(prod*ans[*it])%mod;} if(prod_zero == 0) paths.push_back(make_pair(cur_sum,(cur_ways*prod)%mod)); else paths.push_back(make_pair(cur_sum,0)); ALL_THE(G[R],it) if(*it != par[R]) { if(ans[*it] == 0) prod_zero--; else prod =(prod*ans_inv[*it])%mod; if(prod_zero == 0) DFS_brute(*it,cur_sum+val[*it],(cur_ways*prod)%mod,paths); else DFS_brute(*it,cur_sum+val[*it],0,paths); if(ans[*it] == 0) prod_zero++; else prod =(prod*ans[*it])%mod;} } int P; vector F(100000); vector shift(100000), F_v(100000); vector mul(100000), mul_inv(100000); vector< map > compress(100000); void DFS(int R) { vector son; int heavy =-1; ALL_THE(G[R],it) if(par[*it] == R) { DFS(*it); if(F_v[R] != F_v[*it]) { paths_son[*it].clear(); DFS_brute(*it,val[*it],1,paths_son[*it]); son.push_back(*it);} else heavy =*it;} if(heavy == -1) { // leaf if(val[R] >= 0) ans[R] =ans_inv[R] =1; F[F_v[R]].put(compress[F_v[R]][val[R]],1); return;} vector prod_lft(son.size()+1,1), prod_rt(son.size()+1,1); for(int i =0; i < (int)son.size(); i++) prod_lft[i+1] =(prod_lft[i]*ans[son[i]])%mod; prod_rt[son.size()] =ans[heavy]; for(int i =(int)son.size()-1; i >= 0; i--) prod_rt[i] =(prod_rt[i+1]*ans[son[i]])%mod; if(val[R] >= 0) ans[R] =prod_rt[0]; int f =F_v[R]; shift[f] +=val[R]; ans[R] =(ans[R]+prod_lft[son.size()]*F[f].get(compress[f][-shift[f]])%mod*mul[f])%mod; F[f].put(compress[f][val[R]-shift[f]],ans[heavy]*mul_inv[f]); for(int i =son.size()-1; i >= 0; i--) { ALL_THE(paths_son[son[i]],it) ans[R] =(ans[R]+prod_lft[i]*mul[f]%mod*F[f].get(compress[f][-it->ff-shift[f]])%mod*it->ss)%mod; mul[f] =(mul[f]*ans[son[i]])%mod; mul_inv[f] =(mul_inv[f]*ans_inv[son[i]])%mod; if(mul[f] == 0) { F[f].clear(); mul[f] =mul_inv[f] =1;} ALL_THE(paths_son[son[i]],it) F[f].put(compress[f][val[R]+it->ff-shift[f]],it->ss*prod_rt[i+1]%mod*mul_inv[f]); } ans_inv[R] =inv(ans[R]);} void DFS_init(int R, vector &S) { int heavy =-1, Smax =0; ALL_THE(G[R],it) if(par[*it] == -1) { par[*it] =R; DFS_init(*it,S); S[R] +=S[*it]; if(S[*it] > Smax) Smax =S[*it], heavy =*it; } if(heavy == -1) { // leaf F_v[R] =P; shift[P] =0; compress[P] =map(); compress[P][val[R]] =0; P++; return;} F_v[R] =F_v[heavy]; vector son; ALL_THE(G[R],it) if(*it != heavy && par[*it] == R) { paths_son[*it].clear(); DFS_brute(*it,val[*it],1,paths_son[*it]); son.push_back(*it);} int f =F_v[R]; shift[f] +=val[R]; compress[f][-shift[f]] =compress[f][val[R]-shift[f]] =0; for(int i =son.size()-1; i >= 0; i--) ALL_THE(paths_son[son[i]],it) compress[f][-it->ff-shift[f]] =compress[f][val[R]+it->ff-shift[f]] =0; } int main() { cin.sync_with_stdio(0); cin.tie(0); cout << fixed << setprecision(10); int T; scanf(" %d",&T); for(int t =0; t < T; t++) { int N; scanf(" %d",&N); val.clear(); val.resize(N); for(int i =0; i < N; i++) scanf(" %d",&val[i]); G.clear(); G.resize(N); for(int i =0; i < N-1; i++) { int a,b; scanf(" %d %d",&a,&b); G[--a].push_back(--b); G[b].push_back(a);} par.clear(); par.resize(N,-1); par[0] =0; ans.clear(); ans.resize(N,0); ans_inv.clear(); ans_inv.resize(N); vector S(N,1); P =0; DFS_init(0,S); for(int i =0; i < P; i++) { int m =compress[i].size(); shift[i] =0; mul[i] =mul_inv[i] =1; ALL_THE(compress[i],it) it->ss =m--; F[i].resize(compress[i].size());} DFS(0); if(ans[0] < 0) ans[0] +=mod; printf("%lld\n",(long long)ans[0]);} return 0;} // look at my code // my code is amazing