题目链接:Codeforces - Numbers on Tree
首先证明:n个节点一定可以用1-n的数字去放。
因为1-n的数字都是不同的,那么不会有相对大小的问题,不会有节点之间相互影响而导致答案错误。放相同值的节点也就是少一个差值,我们完全可以用放的方式去避免,比如小的放在大的上面。
其次证明:如果节点的C值小于节点的size,那么一定存在这种方案。
我们从顶点开始放,因为我们放1到n的数字,那么有多少个数字没放是一定的,所以我们相当于是从没放的数字当中找第C+1大的数字放上去,然后标记放的数字,向下递归。一定满足。
AC代码:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e3+10;
int n,res[N],p[N],c[N],rt,sz[N],vis[N];
int head[N],nex[N],to[N],tot;
inline void add(int a,int b){to[++tot]=b; nex[tot]=head[a]; head[a]=tot;}
void dfs_sz(int x){
sz[x]=1;
for(int i=head[x];i;i=nex[i]){
dfs_sz(to[i]); sz[x]+=sz[to[i]];
}
}
void dfs(int x){
int cnt=0;
for(int i=1;i<=n;i++){
if(!vis[i]) cnt++; if(cnt==c[x]+1){res[x]=i; break;}
}
vis[res[x]]=1;
for(int i=head[x];i;i=nex[i]) dfs(to[i]);
}
signed main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>p[i]>>c[i];
if(!p[i]) rt=i; if(p[i]) add(p[i],i);
}
dfs_sz(rt);
for(int i=1;i<=n;i++) if(c[i]>=sz[i]) return puts("NO"),0;
dfs(rt); puts("YES");
for(int i=1;i<=n;i++) cout<<res[i]<<' ';puts("");
return 0;
}