#include <stdio.h>
#include <string.h>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;
#define NMAX 200100
set<pair<int, int> > vset;
char visited[NMAX];
int v[NMAX], o[NMAX], stk[NMAX], nidx[NMAX], parent[NMAX], sparent[NMAX], lmin[NMAX], lmax[NMAX], cmax[NMAX];
vector<int> neigh[NMAX], cbest;
vector<pair<pair<int, int>, int> > intv;
set<pair<int, int> > sbest;
int oidx, i, j, k, N, li, ls, niv, cnt, vmax, cc;
void bfs() {
memset(visited, 0, sizeof(visited));
memset(parent, 0, sizeof(parent));
o[1] = 1;
li = ls = 1;
visited[1] = 1;
while (li <= ls) {
i = o[li];
for (k = neigh[i].size() - 1; k >= 0; k--) {
j = neigh[i][k];
if (!visited[j]) {
visited[j] = 1;
ls++;
o[ls] = j;
parent[j] = i;
}
}
li++;
}
// Make the neigh[i] vector contain only the sons of the node i.
for (i = 1; i <= N; i++)
neigh[i].clear();
for (i = 2; i <= N; i++)
neigh[parent[i]].push_back(i);
}
void dfs() {
pair<int, int> p;
set<pair<int, int> >::iterator it;
memset(sparent, 0, sizeof(sparent));
niv = 1;
stk[niv] = 1;
nidx[niv] = 0;
vset.insert(make_pair(v[1], 1));
lmin[1] = cnt = 1;
while (niv > 0) {
if (nidx[niv] == neigh[stk[niv]].size()) {
vset.erase(make_pair(v[stk[niv]], stk[niv]));
lmax[stk[niv]] = cnt;
niv--;
} else {
i = neigh[stk[niv]][nidx[niv]];
nidx[niv]++;
p = make_pair(v[i], 0);
it = vset.lower_bound(p);
if (it != vset.end()) {
sparent[i] = (*it).second;
}
niv++;
stk[niv] = i;
nidx[niv] = 0;
vset.insert(make_pair(v[i], i));
cnt++;
lmin[i] = cnt;
}
}
// Make the neigh[i] vector contain only the supersons.
for (i = 1; i <= N; i++) {
neigh[i].clear();
}
for (i = 1; i <= N; i++)
neigh[sparent[i]].push_back(i);
lmin[0] = 0;
lmax[0] = N;
o[0] = 0;
}
void compute() {
set<pair<int, int> >::iterator it;
pair<int, int> p;
for (oidx = N; oidx >= 0; oidx--) {
i = o[oidx];
intv.clear();
for (k = neigh[i].size() - 1; k >= 0; k--) {
j = neigh[i][k];
intv.push_back(make_pair(make_pair(lmax[j], lmin[j]), cmax[j]));
}
sort(intv.begin(), intv.end());
// Run a DP on a set of intervals. Each interval has an associated cost. Select a subset of these intervals
// such that no two intervals intersect and their total cost is maximum.
if (intv.size() == 0) {
cmax[i] = 1;
} else {
cbest.clear();
sbest.clear();
for (j = 0; j < intv.size(); j++) {
vmax = 0;
if (j > 0)
vmax = cbest[cbest.size() - 1];
cc = intv[j].second;
p.first = -intv[j].first.second;
p.second = -1;
it = sbest.upper_bound(p);
if (it != sbest.end())
cc += (*it).second;
if (cc > vmax)
vmax = cc;
cbest.push_back(vmax);
sbest.insert(make_pair(-intv[j].first.first, vmax));
}
cmax[i] = 1 + cbest[cbest.size() - 1];
}
}
}
int main() {
// Read the input data.
freopen("guvern.in", "r", stdin);
scanf("%d", &N);
for (k = 1; k < N; k++) {
scanf("%d %d", &i, &j);
neigh[i].push_back(j);
neigh[j].push_back(i);
}
for (i = 1; i <= N; i++)
scanf("%d", &v[i]);
// Run a BFS on the tree in order to define the parent-son relationships.
bfs();
// Run a DFS on the tree.
dfs();
// Compute the result.
compute();
// Print the result.
freopen("guvern.out", "w", stdout);
printf("%d\n", cmax[0] - 1);
return 0;
}