CF 600 E Lomsat gelral (DSU on tree)

题意:给出一个树,求出每个节点的子树中出现次数最多的颜色的编号和

思路:dsu on tree 。暴力求轻边的答案,再加上重边的答案。

#include<bits/stdc++.h>
#define LL long long 
using namespace std;
const int MAXN = 1e5 + 10;
inline int read() {
    char c = getchar(); int x = 0, f = 1;
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}
int N, col[MAXN], son[MAXN], siz[MAXN], cnt[MAXN], Mx, Son;
LL sum = 0, ans[MAXN];
vector<int> v[MAXN];
void dfs(int x,int fa)
{
	siz[x]=1;
	for(int i=0;i<v[x].size();i++){
		int to=v[x][i];
		if(to==fa) continue;
		dfs(to,x);
		siz[x]+=siz[to];
		if(siz[to]>siz[son[x]]) son[x]=to;
	}	
} 
void add(int x,int fa,int val)
{
	cnt[col[x]]+=val;
	if(cnt[col[x]]> Mx) Mx=cnt[col[x]],sum=col[x];
	else if(cnt[col[x]] == Mx) sum+=(LL)col[x];
	for(int i=0;i<v[x].size();i++){
		int to=v[x][i];
		if(to==fa || to ==Son) continue;
		add(to,x,val);
	}
}
void dfs2(int x,int fa,int opt){
	for(int i=0;i<v[x].size();i++){
		int to=v[x][i];
		if(to==fa) continue;
		if(to!=son[x]) dfs2(to,x,0);
	}
	if(son[x]) dfs2(son[x],x,1),Son=son[x];
	add(x,fa,1);Son=0;
	ans[x]=sum;
	if(!opt) add(x,fa,-1),sum=0,Mx=0;
}
int main()
{
	N=read();
	for(int i=1;i<=N;i++) col[i]=read();
	for(int i=1;i<=N-1;i++){
		int x=read(),y=read();
		v[x].push_back(y);
		v[y].push_back(x);
	}
	dfs(1,0);
	dfs2(1,0,0);
	for(int i=1;i<=N;i++) printf("%lld ",ans[i]);
	
}

  

原文地址:https://www.cnblogs.com/The-Pines-of-Star/p/12288482.html