zoukankan      html  css  js  c++  java
  • 2019 Sichuan Province Programming Contest D

    想清楚它不是DP而是贪心就好做了

    首先, 我们称子树刚好包含所有某一颜色的点为临界点, 那我们要优先选择深度越深的临界点越好
    用另一种方式来说, 在dfs的过程中, 第一次发现有一个点恰好为临界点,那么就选择这个点为分界线新增一个答案, 很容易想清楚, 选择越深的肯定更优, 让其它点的有更多分块的机会

    这道题也有两种做法, 一种是找到每个颜色的临界点, 排序一遍再染色一遍即可
    另一个方法是用dsu on tree, 不需要找lca, 每次找到满足条件的时候就ans++, 暴力求解即可
    这里给出第一种方法的代码

    #include <iostream>
    #include <vector>
    #include <string>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int N = 1e5 + 10;
    #define fi first
    #define se second
    #define mp make_pair
    #define sz(v) ((int)(v).size())
    #define debug(a) cout << #a << " = " << a << endl;
    typedef long long ll;
    typedef pair <int, int> P;
    vector < int > edge[N];
    const ll MOD = 1e9 + 7;
    int n, m;
    int a[N], Size[N], dep[N], fa[N], hs[N], tot;
    int minn[N], maxn[N], dfn;
    void dfs(int u, int f, int d) {
        dep[u] = d; fa[u] = f; Size[u] = 1; dfn++;
        if (minn[a[u]] > n)
            minn[a[u]] = u;
        maxn[a[u]] = u;
        for (int i = 0; i < sz(edge[u]); i++) {
            int v = edge[u][i];
            if (v == fa[u]) continue;
            dfs(v, u, d + 1);
            if (Size[v] > Size[hs[u]])  hs[u] = v;
            Size[u] += Size[v];
        }
    }
    
    int top[N];
    void dfs2(int u, int T) {
        top[u] = T;
        if (!hs[u]) return ;
        dfs2(hs[u], T);
        for (int i = 0; i < sz(edge[u]); i++){
            int v = edge[u][i];
            if (hs[u] == v || v == fa[u]) continue;
            dfs2(v, v);
        }
    }
    
    inline int Lca(int u, int v) {
        while (top[u] != top[v]) {
            if (dep[top[u]] < dep[top[v]])  swap(u, v);
            u = fa[top[u]];
        }
        return dep[u] > dep[v] ? v : u;
    }
    
    struct node {
        int a, b, c;
        inline bool operator < (const node & o) const {
            return a > o.a;
        }
    } v[N];
    
    int col[N];
    bool vis[N];
    void add(int u) {
        col[a[u]] = true; vis[u] = true;
        for (int i = 0; i < sz(edge[u]); i++) {
            int v = edge[u][i];
            if (v == fa[u] || vis[v]) continue;
            add(v);
        }
    }
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int T;
        cin >> T;
        for (int Case = 1; Case <= T; Case++) {
            memset(minn, 0x3f, sizeof(minn));
            memset(maxn, 0xff, sizeof(maxn));
            cin >> n; tot = 0;
            for (int i = 1; i <= n; i++)    cin >> a[i];
            for (int i = 1; i < n; i++) {
                int u, v;
                cin >> u >> v;
                edge[u].push_back(v);
                edge[v].push_back(u);
            }
            dfs(1, 0, 0);
            dfs2(1, 1);
            for (int i = 1; i <= n; i++)
                if (minn[i] <= n && maxn[i] > 0) {
                    int l = Lca(minn[i], maxn[i]);
                    v[++tot] = {dep[l], l, i};
                }
            sort(v + 1, v + tot + 1);
            int ans = 0;
            for (int i = 1; i <= tot; i++) {
                if (col[v[i].c]) continue;
                add(v[i].b);  ans++;   
            }
            for (int i = 1; i <= n; i++)    
                vis[i] = false, col[i] = false, hs[i] = 0, edge[i].clear();
            cout << "Case " << Case << ": " << ans << endl;
        }
        return 0;
    }
    
  • 相关阅读:
    java冒泡排序
    正则表达式手册
    简单介绍事务
    Java经典编程30题(中)
    Java经典编程30题(下)
    负载均衡-Nginx
    react入门
    Mybatis && Mybatis-plus
    java设计模式-委派模式
    java8新特性
  • 原文地址:https://www.cnblogs.com/cminus/p/14501856.html
Copyright © 2011-2022 走看看