(树上问题还在找感觉阶段)
子树当中只能与最近的相同点构边,所以每次递归将当前节点的 cnt 记为 1;
递归到的点先行记录与自己相同颜色的 cnt 值(因为在递归该点的 son 时 cnt 会重置);
每个点的子项遍历结束时,更新 ans 同时为该点的 cnt 值在 fa 时该点 cnt 的基础上 +1,确保若 fa 与 son 不同,则存在非子树连接的情况要 +1;
(性质:子树最近点相连,或父节点不同于子节点时,可出现非子树相连)
(实现:子树情况不断更新 cnt 为 1,非子树情况通过累加但不更新实现跨树连接)
(巧用dfs序确保跨树连接的非重与覆盖)
(树上问题和 dfs 真不会(汗
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int max_n=2e5+5;
vector<int>tree[max_n];
ll ans;
int n,c[max_n],cnt[max_n];
void clear()
{
ans=0;
for(int i=1;i<=n;i++){
tree[i].clear();
cnt[i]=0;
}
}
void dfs(int u,int fa)
{
int back=cnt[c[u]];
for(auto ti:tree[u]){
if(ti^fa){
cnt[c[u]]=1;
dfs(ti,u);
}
}
ans+=back;cnt[c[u]]=back+1;
}
void solve()
{
cin>>n;
for(int i=1;i<=n;i++)cin>>c[i];
for(int i=1;i<=n-1;i++){
int u,v;
cin>>u>>v;
tree[u].push_back(v);
tree[v].push_back(u);
}
dfs(1,0);
cout<<ans<<endl;
clear();
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int _t;cin>>_t;
while(_t--){
solve();
}
return 0;
}