zoukankan      html  css  js  c++  java
  • Codeforces 600 E. Lomsat gelral (dfs启发式合并map)

    题目链接:http://codeforces.com/contest/600/problem/E

    给你一棵树,告诉你每个节点的颜色,问你以每个节点为根的子树中出现颜色次数最多的颜色编号和是多少。

    最容易想到的是n*n的暴力,但是会超时。所以这里用到类似并查集的合并,对于每个子树颜色种数少的合并到颜色种数大的当中。

    不懂的看代码应该可以明白。

     1 //#pragma comment(linker, "/STACK:102400000, 102400000")
     2 #include <algorithm>
     3 #include <iostream>
     4 #include <cstdlib>
     5 #include <cstring>
     6 #include <cstdio>
     7 #include <vector>
     8 #include <cmath>
     9 #include <ctime>
    10 #include <list>
    11 #include <set>
    12 #include <map>
    13 using namespace std;
    14 typedef long long LL;
    15 typedef pair <int, int> P;
    16 const int N = 1e5 + 5;
    17 map <int, int> cnt[N]; //first代表颜色编号,second代表出现次数
    18 map <int, LL> sum[N]; //first代表出现次数,second代表颜色编号之和
    19 LL ans[N];
    20 int head[N], tot, a[N];
    21 struct Edge {
    22     int next, to;
    23 }edge[N << 1];
    24 
    25 void init() {
    26     memset(head, -1, sizeof(head));
    27 }
    28 
    29 inline void add(int u, int v) {
    30     edge[tot].next = head[u];
    31     edge[tot].to = v;
    32     head[u] = tot++;
    33 }
    34 
    35 void dfs(int u, int p) {
    36     cnt[u][a[u]] = 1; //初始化:a[u]颜色出现一次
    37     sum[u][1] = (LL)a[u]; //初始化:出现一次的颜色之和为a[u]
    38     for(int i = head[u]; ~i; i = edge[i].next) {
    39         int v = edge[i].to;
    40         if(v == p)
    41             continue;
    42         dfs(v, u);
    43         if(cnt[u].size() < cnt[v].size()) { //颜色种类少的合并到颜色种类多的,u为颜色种类多的子树
    44             swap(cnt[u], cnt[v]);
    45             swap(sum[u], sum[v]);
    46         }
    47         for(auto it: cnt[v]) {
    48             cnt[u][it.first] += it.second; //it.first颜色出现次数合并累加
    49             int temp = cnt[u][it.first]; //temp为it.first颜色次数
    50             sum[u][temp] += (LL)it.first; //累加出现temp次的颜色
    51         }
    52         cnt[v].clear(); //清空
    53         sum[v].clear(); 
    54     }
    55     ans[u] = sum[u].rbegin()->second; //最大出现次数的颜色之和
    56 }
    57 
    58 int main()
    59 {
    60     init();
    61     int n, u, v;
    62     scanf("%d", &n);
    63     for(int i = 1; i <= n; ++i) {
    64         scanf("%d", a + i);
    65     }
    66     for(int i = 1; i < n; ++i) {
    67         scanf("%d %d", &u, &v);
    68         add(u, v);
    69         add(v, u);
    70     }
    71     dfs(1, -1);
    72     for(int i = 1; i <= n; ++i) {
    73         printf("%lld%c", ans[i], i == n? '
    ': ' ');
    74     }
    75     return 0;
    76 }
  • 相关阅读:
    redis 3 通用指令
    查看表索引
    truncate的用法
    Java(0)_ 安装jdk
    Java(9)_ 集合(3)
    Java(10)_File&递归&字节流
    Java(8)_ 集合(2)
    Appium+python的单元测试框架unittest(3)——discover
    Appium+python的单元测试框架unittest(2)——fixtures
    爬楼梯
  • 原文地址:https://www.cnblogs.com/Recoder/p/5844135.html
Copyright © 2011-2022 走看看