• GMOJ 6807 tree 题解


    把问题转化

    1. 选取一个子树包含所有颜色,答案为子树外到子树根最长链的长度

    2. 选取一个子树使得原树去掉该子树包含所有颜色,答案为子树内到子树根最长链的长度

    那么以上情况取最大值即为答案。把问题转化成了求子树的颜色种类,是典型的DSU on Tree.

    分开来做即可。

    但仍需常数优化,预处理从下向上的最长链和次长链,两种情况一起做。

    #include <algorithm>
    #include <cstdio>
    
    using namespace std;
    
    const int maxn = 1000000, maxm = 100000;
    
    class Tree {
        public:
            int n, m, col[maxn + 1], ind[maxn + 1], to[2 * maxn - 1], link[2 * maxn - 1],
                son[maxn + 1], size[maxn + 1], len[maxn + 1], ans, f[maxm + 1],
                g[maxm + 1], ver[maxm + 1], ml[maxn + 1], sl[maxn + 1];
    
            void addSide(int u, int v) {
                m++;
                to[m] = v;
                link[m] = ind[u];
                ind[u] = m;
            }
    
            void init(int o, int fa) {
                len[o] = 1, size[o] = 1, son[o] = 0, ml[o] = 0, sl[o] = 0;
                for (int i = ind[o]; i; i = link[i]) {
                    if (to[i] != fa) {
                        init(to[i], o);
                        len[o] = max(len[o], len[to[i]] + 1);
                        if (len[ml[o]] <= len[to[i]]) {
                            sl[o] = ml[o], ml[o] = to[i];
                        } else if (len[sl[o]] <= len[to[i]]) {
                            sl[o] = to[i];
                        }
                        size[o] += size[to[i]];
                        if (size[son[o]] < size[to[i]]) {
                            son[o] = to[i];
                        }
                    }
                }
            }
    
            void solve(int o, int fa, int up, bool keep, bool makeAns) {
                int a = ml[o], b = sl[o];
                for (int i = ind[o]; makeAns && i; i = link[i]) {
                    if (to[i] != fa && to[i] != son[o]) {
                        solve(to[i], o, max(up, to[i] == a ? len[b] : len[a]) + 1, false, true);
                    }
                }
                if (son[o]) {
                    solve(son[o], o, max(up, son[o] == a ? len[b] : len[a]) + 1, true, makeAns);
                }
                for (int i = ind[o]; i; i = link[i]) {
                    if (to[i] != fa && to[i] != son[o]) {
                        solve(to[i], o, 0, true, false);
                    }
                }
    
                if (ver[col[o]] != ver[0]) {
                    ver[col[o]] = ver[0];
                    g[col[o]] = 0;
                }
                if (!g[col[o]]) {
                    f[0]++;
                }
                g[col[o]]++;
                if (g[col[o]] == f[col[o]]) {
                    g[0]++;
                }
                if (makeAns) {
                    if (f[0] == col[0]) {
                        ans = max(ans, up + 1);
                    }
                    if (!g[0]) {
                        ans = max(ans, len[o] + 1);
                    }
                }
                if (!keep) {
                    ver[0]++, f[0] = g[0] = 0;
                }
            }
    };
    
    int read() {
        int ret = 0;
        char c;
        for (c = getchar(); c < '0' || c > '9'; c = getchar());
        for (; c >= '0' && c <= '9'; c = getchar()) {
            ret = ret * 10 + c - '0';
        }
        return ret;
    }
    
    int main() {
        freopen("tree.in", "r", stdin);
        freopen("tree.out", "w", stdout);
    
        static Tree tree;
        int n = read(), m = read();
        tree.n = n;
        tree.col[0] = m;
        for (int i = 1; i <= n; i++) {
            tree.col[i] = read();
            tree.f[tree.col[i]]++;
        }
        for (int i = 1; i < n; i++) {
            int u = read(), v = read();
            tree.addSide(u, v);
            tree.addSide(v, u);
        }
        tree.g[0] = m;
        tree.init(1, 0);
        tree.solve(1, 0, 0, true, true);
        printf("%d
    ", tree.ans);
    
        fclose(stdin);
        fclose(stdout);
        return 0;
    }
    
    
  • 相关阅读:
    linux下samba服务器的搭建(案列模拟)
    linux下nfs服务器的搭建
    linux 下 php+gd2+freetype+jpeg+png+zlib编译安装
    linux下xcache的安装
    wget如何设置代理
    实验记录:vsftp整合mysql-pam管理虚拟账号
    tr命令 实例
    sed学习笔记
    Byte、KB、MB、GB、TB、PB转换
    对lombbok @slf4j 进行测试用例
  • 原文地址:https://www.cnblogs.com/BunnyLutts/p/13909759.html
Copyright © 2020-2023  润新知