zoukankan      html  css  js  c++  java
  • HDU6504 Problem E. Split The Tree【dsu on tree】

    Problem E. Split The Tree

    Problem Description
    You are given a tree with n vertices, numbered from 1 to n. ith vertex has a value wi
    We define the weight of a tree as the number of different vertex value in the tree.
    If we delete one edge in the tree, the tree will split into two trees. The score is the sum of these two trees’ weights.
    We want the know the maximal score we can get if we delete the edge optimally

    给出一棵根为(1)的树,每个节点有权值,现在断开一条边,把树一分为二,记一棵树的贡献为这棵树里所有节点中不同权值的数量,现在要计算断开边之后两棵树的贡献的和的最大值

    现在有一棵子树,为了得到答案,我们只要知道它里面出现过的各个权值有多少个,记原树中各个权值出现的数量是(cnt[i]),分开之后的一棵子树的各个权值出现的数量使(dcnt[i]),只要出现(dcnt[i] e cnt[i] and dcnt[i] e 0),对答案的贡献就(+1),这个可以(O(1))处理,那么就可以树上启发式合并了

    //#pragma GCC optimize("O3")
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<bits/stdc++.h>
    using namespace std;
    function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
    const int MAXN = 1e5+7;
    int n,w[MAXN],ret,tmp,cnt[MAXN],dcnt[MAXN],son[MAXN],sz[MAXN],st[MAXN],ed[MAXN],id[MAXN],dfn;
    vector<int> G[MAXN];
    
    void dfs(int u){
        sz[u] = 1; son[u] = 0;
        st[u] = ++dfn; id[dfn] = u;
        for(int v : G[u]){
            dfs(v);
            sz[u] += sz[v];
            if(sz[v]>sz[son[u]]) son[u] = v;
        }
        ed[u] = dfn;
    }
    void update(int val, int inc){
        if(inc==1){
            if(!dcnt[val]) tmp++;
            dcnt[val]++;
            if(dcnt[val]==cnt[val]) tmp--;
        }
        else{
            if(dcnt[val]==cnt[val]) tmp++;
            dcnt[val]--;
            if(!dcnt[val]) tmp--;
        }
    }
    void search(int u, bool clear){
        for(int v : G[u]) if(v!=son[u]) search(v,true);
        if(son[u]) search(son[u],false);
        for(int v : G[u]) if(v!=son[u]) for(int i = st[v]; i <= ed[v]; i++) update(w[id[i]],1);
        update(w[u],1);
        ret = max(ret,tmp);
        if(clear) for(int i = st[u]; i <= ed[u]; i++) update(w[id[i]],-1);
    }
    void solve(){
        dfn = 0;
        for(int i = 1; i <= n; i++) G[i].clear();
        for(int i = 2; i <= n; i++){
            int par; scanf("%d",&par);
            G[par].push_back(i);
        }
        tmp = 0;
        for(int i = 1; i <= n; i++){
            scanf("%d",&w[i]);
            if(!cnt[w[i]]) tmp++;
            cnt[w[i]]++;
        }
        ret = tmp;
        dfs(1);
        search(1,true);
        printf("%d
    ",ret);
        for(int i = 1; i <= n; i++) cnt[w[i]]--;
    }
    int main(){
        while(scanf("%d",&n)!=EOF) solve();
        return 0;
    }
    
  • 相关阅读:
    oracle按用户导出导入表
    一次简单的springboot+dubbo+flume+kafka+storm+redis系统
    数据库索引学习
    springboot-quartz 实现动态添加,修改,删除,暂停,恢复等功能
    springboot + rabbitmq 整合示例
    springboot-quartz普通任务与可传参任务
    eclipse里maven项目An error occurred while filtering resources解决办法
    job调度时间格式
    多线程发送短信和微信公众号推送消息
    SerializeUtil 序列化,反序列化工具类
  • 原文地址:https://www.cnblogs.com/kikokiko/p/12777567.html
Copyright © 2011-2022 走看看