/*
思路:借鉴 dsu on tree,自底往上进行合并
给每个叶子结点赋初始值为1,每个结点依次合并每个儿子
为了防止冲突,子树在被并入当前结点时,所有结点都要重新编号
最后把当前结点插到子树里去,由于又插进了一个结点,所以再重新编号一次
每个最多被重新编号n次,复杂度O(n^2)
*/
#include<bits/stdc++.h>
#include<vector>
using namespace std;
#define N 2005
int n,p[N],c[N],id[N];
vector<int>G[N];
vector<int> subtree[N];
int root;
void dfs(int u,int pre){
if(G[u].size()==1 && pre==0){
subtree[u].push_back(u);
id[u]=1;return;
}
for(auto v:G[u])
if(v!=pre)dfs(v,u);
int tot=0;
for(auto v:G[u])if(v!=pre){
for(auto x:subtree[v]){
subtree[u].push_back(x);
id[x]+=tot;
}
tot+=subtree[v].size();
subtree[v].clear();
}
stack<int>stk;
while(stk.size())stk.pop();
while(subtree[u].size()>=c[u]){
stk.push(subtree[u].back());
subtree[u].pop_back();
}
subtree[u].push_back(u);
id[u]=c[u];
while(stk.size()){
int now=stk.top();stk.pop();
id[now]++;
subtree[u].push_back(now);
}
}
int size[N];
void getsize(int u,int pre){
size[u]=1;
for(auto v:G[u]){
if(v==pre)continue;
getsize(v,u);size[u]+=size[v];
}
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>p[i]>>c[i];
c[i]++;
G[i].push_back(p[i]);
G[p[i]].push_back(i);
if(p[i]==0)root=i;
}
getsize(root,0);
for(int i=1;i<=n;i++)
if(size[i]<c[i]){
puts("NO");return 0;
}
dfs(root,0);
puts("YES");
for(int i=1;i<=n;i++)cout<<id[i]<<" ";
}