#include<bits/stdc++.h>
using namespace std;
int n, k;
vector<vector<int> > tree;
vector<int> primes[1000005];
bool isnotprime[1000005];
int a[100005];
void pre(){
// FIXME: It's 1e6 not 1e2
for(int i = 2; i <= 1e2; ++i){
if(isnotprime[i]) continue;
primes[i].push_back(i);
for(int j = i; j <= 1e2; j += i){
isnotprime[j] = true;
primes[j].push_back(i);
}
}
}
map<int, long long> dp[100005][15]; // (node, k, prime)
long long dp1[100005][15];
long long res;
void dfs(int root, int parent){
for(int child : tree[root]){
if(child != parent) dfs(child, root);
}
for(int p : primes[a[root]]){
for(int i = 0; i < k; ++i){
if(i == 0){
dp[root][i][p] = 1;
if(k == 1) res = 1;
dp1[root][i] = 1;
}
else {
dp[root][i][p] = -1e9;
dp1[root][i] = -1e9;
}
}
}
for(int p : primes[a[root]]){
for(int remaining = 0; remaining < k; ++remaining){
// FIXME: Currently, it's iterating every child pairs (ch1, ch2)
// and calculating the best possible path.
// Can be done with single iteration. Optimize if TLE.
for(int ch1 : tree[root]){
if(ch1 == parent) continue;
for(int ch2 : tree[root]){
if(ch2 == parent) continue;
if(ch1 == ch2){
int rem = ((remaining - 1) % k + k) % k;
if(remaining == 0){
dp[root][remaining][p] = max(dp[root][remaining][p], 1 + dp1[ch1][rem]);
}
else{
if(dp[ch1][rem][p] > 0){
dp[root][remaining][p] = max(dp[root][remaining][p], 1 + dp[ch1][rem][p]);
}
}
if(dp[root][remaining][p] % k == 0) res = max(res, dp[root][remaining][p]);
dp1[root][remaining] = max(dp1[root][remaining], dp[root][remaining][p]);
}
else{
int lefttree_rem = ((remaining - 1) % k + k) % k;
int righttree_rem = (k - (((remaining + 2) % k + k) % k)) % k;
long long c = -1e9;
int x, y;
if(remaining == 0 || remaining == k - 1){
if(remaining == 0 && remaining == k - 1){
x = dp1[ch1][lefttree_rem];
y = dp1[ch2][righttree_rem];
if(x > 0 && y > 0){
c = 1 + x + y;
}
}
else if(remaining == 0 && remaining != k - 1){
x = dp1[ch1][lefttree_rem];
y = dp[ch2][righttree_rem][p];
if(x > 0 && y > 0){
c = 1 + x + y;
}
}
else if(remaining == k - 1 && remaining != 0){
x = dp[ch1][lefttree_rem][p];
y = dp1[ch2][righttree_rem];
if(x > 0 && y > 0){
c = 1 + x + y;
}
}
}
else{
x = dp[ch1][lefttree_rem][p];
y = dp[ch2][righttree_rem][p];
if(x > 0 && y > 0){
c = 1 + x + y;
}
}
if(c % k == 0) res = max(res, c);
}
}
}
}
}
}
int dfs1(int cur, int par){
vector<long long> p;
for(int child : tree[cur]){
if(child != par){
int ret = dfs1(child, cur);
p.push_back(ret);
}
}
if(p.size() == 1){
sort(p.begin(), p.end());
if(a[cur] > 1) res = max(res, 1 + p[p.size() - 1]);
}
else if(p.size() >= 2){
sort(p.begin(), p.end());
if(a[cur] > 1) res = max(res, 1 + p[p.size() - 1] + p[p.size() - 2]);
}
if(a[cur] > 1){
if(p.size()) p[p.size() - 1] += 1;
else p.push_back(1);
res = max(res, p.back());
}
else{
p.clear();
p.push_back(0);
}
return p[p.size() - 1];
}
int main(){
pre();
cin >> n >> k;
tree.resize(n + 5);
int x, y;
for(int i = 1; i < n; ++i){
scanf("%d%d", &x, &y);
tree[x].push_back(y);
tree[y].push_back(x);
}
for(int i = 1; i <= n; ++i){
scanf("%d", &a[i]);
}
if(k == 1){
dfs1(1, -1);
cout << res << endl;
return 0;
}
dfs(1, -1);
cout << res << endl;
return 0;
}