dfs+哈希
/*
求最长公共子序列,每次同时维护两个树
*/
#include <iostream>
#include <cstring>
#include <algorithm>
#include <unordered_map>
using namespace std;
const int N = 200010, M = N * 2;
int h[2][N], e[2][M], ne[2][M], idx;
int w1[N], w2[N];
int n, m;
void add(int i, int a, int b){
e[i][idx] = b, ne[i][idx] = h[i][a], h[i][a] = idx ++;
}
int dfs(int u1, int u2, int fa1, int fa2){
int res = 0;
unordered_map<int, int> hs;
//遍历第一个数,将其能到的子节点加入到集合S
for (int i = h[0][u1]; ~i; i = ne[0][i]){
int j = e[0][i];
if (j == fa1) continue;
hs[w1[j]] = j;//权值映射到点
}
for (int i = h[1][u2]; ~i; i = ne[1][i]){
int j = e[1][i];
if (j == fa2) continue;
if (hs.count(w2[j])){//哈希表中有,就是有最长公共子序列
res = max(dfs(hs[w2[j]], j, u1, u2), res);//取最长公共最长子序列
}
}
return res + 1;//多了u,加一
}
int main(){
scanf("%d%d", &n, &m);
memset(h, -1, sizeof h);
for (int i = 1; i <= n; i ++) scanf("%d", &w1[i]);
for (int i = 1; i <= m; i ++) scanf("%d", &w2[i]);
for (int i = 0; i < n - 1; i ++){
int a, b;
scanf("%d%d", &a, &b);
add(0, a, b); add(0, b, a);
}
for (int i = 0; i < m - 1; i ++){
int a, b;
scanf("%d%d", &a, &b);
add(1, a, b); add(1, b, a);
}
int res = 0;
if (w1[1] == w2[1]){
res = dfs(1, 1, 0, 0);
}
printf("%d\n", res);
return 0;
}