并查集 + 树形结构(逆向建树) 920ms
#include<bits/stdc++.h>
#define ll long long
#define fir first
#define sec second
#define PB push_back
#define ALL(a) begin(a),end(a)
#define mem(a,n) memset(a,n,sizeof(a))
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl '\n'
using namespace std;
const int maxn = 2e5+5;
int n, pre[maxn];
int find(int x)
{
return pre[x]==x ? x : pre[x] = find(pre[x]);
}
struct node
{
int val, id;
bool operator<(node aa)
{
return val < aa.val;
}
}pt[maxn];
vector<int> eg[maxn], as[maxn];
int vis[maxn], dep[maxn];
void dfs(int x, int far)
{
for(auto y:as[x])
{
if(y==far) continue;
dep[y] = dep[x] + 1;
dfs(y, x);
}
}
void solve()
{
cin>>n;
for(int i=1;i<=n;i++)
{
pre[i] = i;
eg[i].clear();
as[i].clear();
vis[i] = 0;
dep[i] = 0;
}
int u, v;
for(int i=2;i<=n;i++)
{
cin>>u>>v;
eg[u].PB(v);
eg[v].PB(u);
}
for(int i=1;i<=n;i++) cin>>pt[i].val, pt[i].id = i;
sort(pt+1, pt+1+n);
vis[pt[1].id] = 1;
for(int i=2;i<=n;i++)
{
int x = pt[i].id;
for(auto y:eg[x])
{
if(vis[y]) // 只对权值比自己小的点连边
{
int fy = find(y); // 祖先
pre[fy] = x; // 合并
as[x].PB(fy); // 加边
}
}
vis[x] = 1;
}
dep[pt[n].id] = 1;
dfs(pt[n].id, -1);
for(int i=1;i<=n;i++) cout<<dep[i]<<endl;
}
int main()
{
IOS;
int _;cin>>_;while(_--)
solve();return 0;
}