#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define endl "\n"
#define int long long
using namespace std;
void SieveOfEratosthenes(int n, bool prime[],
bool primesquare[], int a[])
{
// Create a boolean array "prime[0..n]" and
// initialize all entries it as true. A value
// in prime[i] will finally be false if i is
// Not a prime, else true.
for (int i = 2; i <= n; i++)
prime[i] = true;
// Create a boolean array "primesquare[0..n*n+1]"
// and initialize all entries it as false. A value
// in squareprime[i] will finally be true if i is
// square of prime, else false.
for (int i = 0; i <= (n * n + 1); i++)
primesquare[i] = false;
// 1 is not a prime number
prime[1] = false;
for (int p = 2; p * p <= n; p++) {
// If prime[p] is not changed, then
// it is a prime
if (prime[p] == true) {
// Update all multiples of p
for (int i = p * 2; i <= n; i += p)
prime[i] = false;
}
}
int j = 0;
for (int p = 2; p <= n; p++) {
if (prime[p]) {
// Storing primes in an array
a[j] = p;
// Update value in primesquare[p*p],
// if p is prime.
primesquare[p * p] = true;
j++;
}
}
}
// Function to count divisors
int countDivisors(int n)
{
// If number is 1, then it will have only 1
// as a factor. So, total factors will be 1.
if (n == 1)
return 1;
bool prime[n + 1], primesquare[n * n + 1];
int a[n]; // for storing primes upto n
// Calling SieveOfEratosthenes to store prime
// factors of n and to store square of prime
// factors of n
SieveOfEratosthenes(n, prime, primesquare, a);
// ans will contain total number of distinct
// divisors
int ans = 1;
// Loop for counting factors of n
for (int i = 0;; i++) {
// a[i] is not less than cube root n
if (a[i] * a[i] * a[i] > n)
break;
// Calculating power of a[i] in n.
int cnt = 1; // cnt is power of prime a[i] in n.
while (n % a[i] == 0) // if a[i] is a factor of n
{
n = n / a[i];
cnt = cnt + 1; // incrementing power
}
// Calculating number of divisors
// If n = a^p * b^q then total divisors of n
// are (p+1)*(q+1)
ans = ans * cnt;
}
// if a[i] is greater than cube root of n
// First case
if (prime[n])
ans = ans * 2;
// Second case
else if (primesquare[n])
ans = ans * 3;
// Third casse
else if (n != 1)
ans = ans * 4;
return ans; // Total divisors
}
void addEdge(vector<int> v[],
int x,
int y)
{
v[x].push_back(y);
v[y].push_back(x);
}
// A function to print the path between
// the given pair of nodes.
int ans =1;
void printPath(vector<int> stack, int A[])
{
int i;
for (i = 0; i < (int)stack.size() - 1;
i++) {
// cout << stack[i] << " -> ";
ans = ans* A[stack[i]-1];
}
// cout << stack[i];
ans = ans*A[stack[i]-1];
ans = countDivisors(ans);
}
// An utility function to do
// DFS of graph recursively
// from a given vertex x.
void DFS(vector<int> v[],
bool vis[],
int x,
int y,
vector<int> stack, int A[])
{
stack.push_back(x);
if (x == y) {
// print the path and return on
// reaching the destination node
printPath(stack, A);
return;
}
vis[x] = true;
// A flag variable to keep track
// if backtracking is taking place
int flag = 0;
if (!v[x].empty()) {
for (int j = 0; j < v[x].size(); j++) {
// if the node is not visited
if (vis[v[x][j]] == false) {
DFS(v, vis, v[x][j], y, stack, A);
flag = 1;
}
}
}
if (flag == 0) {
// If backtracking is taking
// place then pop
stack.pop_back();
}
}
// A utility function to initialise
// visited for the node and call
// DFS function for a given vertex x.
void DFSCall(int x,
int y,
vector<int> v[],
int n,
vector<int> stack, int A[])
{
// visited array
bool vis[n + 1];
memset(vis, false, sizeof(vis));
// DFS function call
DFS(v, vis, x, y, stack, A);
}
int32_t main() {
int t;
cin>>t;
while(t--){
int n;
cin>>n;
vector<int> v[n+1], stack;
int a, b;
for(int i=0; i<n-1; i++){
cin>>a>>b;
addEdge(v, a, b);
}
int A[n];
for(int i=0; i<n; i++) cin>>A[i];
int q, source, dest; cin>>q;
for(int i=0; i<q; i++){
cin>>source>>dest;
ans = 1;
DFSCall(source, dest, v, n+1, stack, A);
cout<<ans; cout<<endl;
} }
return 0;
}