zoukankan      html  css  js  c++  java
  • [CF1286B] Numbers on Tree

    给定一棵有根树,每个结点有权值 (a_i),记 (c_i)(i) 的子树中权值 (<a_i) 的点的个数。给定 (c_i),构造 (a_i)(nleq2000)

    Solution

    某个子树内的合法性只和这个子树内权值的相对大小有关,于是一定存在一种合法方案,使得所有点的权值互不相同,不妨设为一个 (n) 的全排列

    于是我们考虑维护一个集合 (S),初态下 (S) 中包含所有点,设 (d_i) 表示 (i) 的子树中权值 (<a_i) 的仍然在 (S) 中的点的个数,显然初态下 (d_i=c_i)

    我们每次从 (S) 中取出所有 (d_i=0) 的点,给这些点赋权

    这些点之间存在祖先关系,那么显然深度浅的点应该赋小权

    于是我们每次取出所有 (d_i=0) 的点把它们扔进一个堆中,每次把堆顶取出来并且给它赋权,同时给它所有祖先的 (d_i-1),如果某个祖先的 (d_i=0) 就把这个祖先扔进堆中

    如果堆空了,但是还有节点没有赋权,则输出 NO

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    const int N = 2005;
    vector <int> g[N];
    priority_queue <pair<int,int> > hp;
    int ans[N],n,p[N],c[N],d[N],fa[N],ind,dep[N];
    
    void dfs(int p) {
        for(int q:g[p]) if(dep[q]==0) {
            dep[q]=dep[p]+1;
            fa[q]=p;
            dfs(q);
        }
    }
    
    signed main() {
        cin>>n;
        for(int i=1;i<=n;i++) cin>>p[i]>>c[i];
        for(int i=1;i<=n;i++) g[p[i]].push_back(i);
        for(int i=1;i<=n;i++) d[i]=c[i];
        int r=0;
        for(int i=1;i<=n;i++) if(p[i]==0) r=i;
        dfs(r);
        for(int i=1;i<=n;i++) if(d[i]==0) hp.push({-dep[i],i});
        while(hp.size()) {
            int p=hp.top().second;
            hp.pop();
            ans[p]=++ind;
            while(p!=r) {
                p=fa[p];
                d[p]--;
                if(d[p]==0 && !ans[p]) hp.push({-dep[p],p});
            }
        }
        if(ind<n) {
            puts("NO");
        }
        else {
            puts("YES");
            for(int i=1;i<=n;i++) cout<<ans[i]<<" ";
        }
    }
    
    
  • 相关阅读:
    rc.local文件
    mysql 常用语句模板
    gradle使用
    Elasticsearch 聚合
    华盛顿大学 Programming Languages
    802.11基础
    802.11简单认证过程
    网络诊断错误归类
    802.1X基础
    终端管理软件tmux
  • 原文地址:https://www.cnblogs.com/mollnn/p/12550069.html
Copyright © 2011-2022 走看看