1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
| #include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+1;
#define ll long long
vector<int> vec[maxn];
int col[maxn],cnt[maxn],vis[maxn],n,top=0; //cnt是每种颜色的数量
ll sum[maxn],ans[maxn]; //sum[i]表示出现次数为i的颜色数量和,sum[top]是答案ans[u]
int son[maxn],siz[maxn];
void dfs1(int u,int fa){
siz[u]=1;
for(int i=0;i<vec[u].size();i++){
if(fa!=vec[u][i]){
dfs1(vec[u][i],u);
siz[u]+=siz[vec[u][i]];
if(siz[vec[u][i]]>siz[son[u]]){ //一开始默认siz[0]=0
son[u]=vec[u][i];
}
}
}
}
void cal(int u,int fa,int val){ //计算树u,sum[top]是答案
sum[cnt[col[u]]]-=col[u];
cnt[col[u]]+=val;
sum[cnt[col[u]]]+=col[u];
if(cnt[col[u]]>top||sum[top]==0){
top=cnt[col[u]];
}
for(int i=0;i<vec[u].size();i++){
if(vec[u][i]==fa||vis[vec[u][i]])
continue;
cal(vec[u][i],u,val);
}
}
void dfs(int u,int fa,bool keep){ //预处理得到u及其子树的答案
for(int i=0;i<vec[u].size();i++){
if(fa==vec[u][i]||vec[u][i]==son[u])
continue;
dfs(vec[u][i],u,0); //先处理轻儿子的树
}
if(son[u])
dfs(son[u],u,1),vis[son[u]]=1; //处理重儿子,保留痕迹
cal(u,fa,1); //这一步才真正是统计树u的答案,
//它在向下计算的时候不会再对已vis标记的重儿子进行dfs,优化在这里了
ans[u]=sum[top];
if(son[u])
vis[son[u]]=0; //已经利用过了此次便利,清除标记
if(!keep)
cal(u,fa,-1); //清除对数组的影响
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
scanf("%d",col+i);
}
for(int i=1,x,y;i<n;i++){
scanf("%d%d",&x,&y);
vec[x].push_back(y);
vec[y].push_back(x);
}
dfs1(1,0);
dfs(1,0,1); //填1是为了省下最后那次遍历
for(int i=1;i<=n;i++)
printf("%lld ",ans[i]);
puts("");
return 0;
}
|