codeforces 600E. Lomsat gelral 启发式合并
给一颗树, 每个节点有初始的颜色值。 1为根节点。定义一个节点的值为, 它的子树中出现最多的颜色的值, 如果有多种颜色出现的次数相同, 那么值为所有颜色的值的和。
每一个叶子节点是一个map, 然后从叶子节点并上去, 注意并的时候把小的map并到大的map里面。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define pb(x) push_back(x) 4 #define ll long long 5 #define mk(x, y) make_pair(x, y) 6 #define lson l, m, rt<<1 7 #define mem(a) memset(a, 0, sizeof(a)) 8 #define rson m+1, r, rt<<1|1 9 #define mem1(a) memset(a, -1, sizeof(a)) 10 #define mem2(a) memset(a, 0x3f, sizeof(a)) 11 #define rep(i, a, n) for(int i = a; i<n; i++) 12 #define ull unsigned long long 13 typedef pair<int, int> pll; 14 const double PI = acos(-1.0); 15 const double eps = 1e-8; 16 const int mod = 1e9+7; 17 const int inf = 1061109567; 18 const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} }; 19 const int maxn = 1e5+5; 20 int head[maxn*2], color[maxn], num, cnt[maxn], id[maxn]; 21 ll anss[maxn], ans[maxn]; 22 struct node 23 { 24 int to, nextt; 25 }e[maxn*2]; 26 void add(int u, int v) { 27 e[num].to = v, e[num].nextt = head[u], head[u] = num++; 28 } 29 map <int, int> m[maxn]; 30 void combine(int &u, int &v) { 31 if(m[u].size()<m[v].size()) 32 swap(u, v); 33 for(auto it = m[v].begin(); it!=m[v].end(); it++) { 34 m[u][it->first] += it->second; 35 if(m[u][it->first]>cnt[u]) { 36 cnt[u] = m[u][it->first]; 37 ans[u] = it->first; 38 } else if(m[u][it->first] == cnt[u]) { 39 ans[u] += it->first; 40 } 41 } 42 } 43 void dfs(int u, int fa) { 44 for(int i = head[u]; ~i; i = e[i].nextt) { 45 int v = e[i].to; 46 if(v == fa) 47 continue; 48 dfs(v, u); 49 combine(id[u], id[v]); 50 } 51 anss[u] = ans[id[u]]; 52 } 53 int main() 54 { 55 mem1(head); 56 int n, x, y; 57 cin>>n; 58 for(int i = 1; i<=n; i++) { 59 scanf("%d", &x); 60 id[i] = i; 61 m[i][x] = 1; 62 cnt[i] = 1; 63 ans[i] = x; 64 } 65 for(int i = 0; i<n-1; i++) { 66 scanf("%d%d", &x, &y); 67 add(x, y); 68 add(y, x); 69 } 70 dfs(1, 0); 71 for(int i = 1; i<=n; i++) { 72 printf("%I64d ", anss[i]); 73 } 74 return 0; 75 }