#include<bits/stdc++.h>usingnamespacestd;classTree{public:intn,timer;vector<vector<int>>adj;vector<set<int>>children;vector<int>tin,tout;vector<longlong>a,entity;Tree(intn){this->n=n;adj.resize(n);tin.resize(n);tout.resize(n);children.resize(n);a.resize(n);entity.resize(2*n+1);timer=0;}public:voiddfs(intsrc,intpar){timer++;tin[src]=timer;entity[timer]=src;for(autochild:adj[src]){if(child!=par){children[src].insert(child);dfs(child,src);}}timer++;tout[src]=timer;entity[timer]=src;}};voidsolve(){intn;cin>>n;Treet(n);for(inti=1;i<n;i++){intpi;cin>>pi;pi--;t.adj[pi].push_back(i);t.adj[i].push_back(pi);}for(inti=0;i<n;i++){cin>>t.a[i];t.a[i]--;}t.dfs(0,-1);longlongans=1;for(inti=0;i<n;i++){// Make sure to exclude tout[i] to avoid empty path.
// We need to partition the range into disjoint subtrees (per children),
// take max in each of them and take their best product.
map<int,int>colors;vector<longlong>paths={1};intmx=0;for(intx=t.tin[i];x<t.tout[i];x++){intentity=t.entity[x];intc_now=t.a[entity];// It was a discovery event.
if(t.tin[entity]==x){colors[c_now]++;mx=max(mx,(int)(colors.size()));}else{// It was a finish event.
colors[c_now]--;if(colors[c_now]==0){colors.erase(c_now);}mx=max(mx,(int)(colors.size()));// This was a finish event, if it is the finish time of
// a direct children, store the subtree max.
if(t.children[i].find(entity)!=t.children[i].end()){paths.push_back(mx);mx=1;}}}sort(paths.begin(),paths.end());intsz=paths.size();if(paths.size()>=2){ans=max(ans,paths[sz-1]*paths[sz-2]);}}cout<<ans<<"\n";}intmain(){intt;cin>>t;for(intzz=0;zz<t;zz++){solve();}return0;}