[CF1286B] Numbers on Tree
Posted mollnn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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]<<" ";
}
}
以上是关于[CF1286B] Numbers on Tree的主要内容,如果未能解决你的问题,请参考以下文章