Evlampiy was gifted a rooted tree. The vertices of the tree are numbered from 1 to n. Each of its vertices also has an integer a_i written on it. For each vertex i, Evlampiy calculated c_i — the number of vertices j in the subtree of vertex i, such that a_j < a_i. 

<image>Illustration for the second example, the first integer is a_i and the integer in parentheses is c_i

After the new year, Evlampiy could not remember what his gift was! He remembers the tree and the values of c_i, but he completely forgot which integers a_i were written on the vertices.

Help him to restore initial integers!

Input

The first line contains an integer n (1 ≤ n ≤ 2000) — the number of vertices in the tree.

The next n lines contain descriptions of vertices: the i-th line contains two integers p_i and c_i (0 ≤ p_i ≤ n; 0 ≤ c_i ≤ n-1), where p_i is the parent of vertex i or 0 if vertex i is root, and c_i is the number of vertices j in the subtree of vertex i, such that a_j < a_i.

It is guaranteed that the values of p_i describe a rooted tree with n vertices.

Output

If a solution exists, in the first line print "YES", and in the second line output n integers a_i (1 ≤ a_i ≤ {10}^{9}). If there are several solutions, output any of them. One can prove that if there is a solution, then there is also a solution in which all a_i are between 1 and 10^9.

If there are no solutions, print "NO".

Examples

Input


3
2 0
0 2
2 0


Output


YES
1 2 1 

Input


5
0 1
1 3
2 1
3 0
2 0


Output


YES
2 3 2 1 2
# ------------------- fast io --------------------
import os
import sys
from io import BytesIO, IOBase
 
BUFSIZE = 8192
 
class FastIO(IOBase):
    newlines = 0
    def __init__(self, file):
        self._fd = file.fileno()
        self.buffer = BytesIO()
        self.writable = "x" in file.mode or "r" not in file.mode
        self.write = self.buffer.write if self.writable else None
 
    def read(self):
        while True:
            b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
            if not b:
                break
            ptr = self.buffer.tell()
            self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr)
        self.newlines = 0
        return self.buffer.read()
 
    def readline(self):
        while self.newlines == 0:
            b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
            self.newlines = b.count(b"\n") + (not b)
            ptr = self.buffer.tell()
            self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr)
        self.newlines -= 1
        return self.buffer.readline()
 
    def flush(self):
        if self.writable:
            os.write(self._fd, self.buffer.getvalue())
            self.buffer.truncate(0), self.buffer.seek(0)
 
 
class IOWrapper(IOBase):
    def __init__(self, file):
        self.buffer = FastIO(file)
        self.flush = self.buffer.flush
        self.writable = self.buffer.writable
        self.write = lambda s: self.buffer.write(s.encode("ascii"))
        self.read = lambda: self.buffer.read().decode("ascii")
        self.readline = lambda: self.buffer.readline().decode("ascii")
 
 
sys.stdin, sys.stdout = IOWrapper(sys.stdin), IOWrapper(sys.stdout)
input = lambda: sys.stdin.readline().rstrip("\r\n")
# ------------------- fast io --------------------
from collections import deque,defaultdict
n=int(input())
tree=[[] for s in range(n)];nums=[];root=0
for s in range(n):
    p,c=map(int,input().split())
    p-=1
    if p!=-1:
        tree[p].append(s);tree[s].append(p)
    else:
        root=s
    nums.append(c)
if n==1:
    if nums[0]==0:
        print("YES")
        print(1)
    else:
        print("NO")
else:
    dp={}
    queue=deque([root]);vis=set([root])
    depth=defaultdict(list);dd={};cv=0;pr=1
    while len(queue)>0:
        v0=queue.popleft()
        for s in tree[v0]:
            if not(s in vis):
                queue.append(s);vis.add(s)
        depth[cv].append(v0);dd[v0]=cv
        pr-=1
        if pr==0:
            pr=len(queue);cv+=1
    cv-=1;broke=False
    while cv>=0:
        for node in depth[cv]:
            count=nums[node]
            if len(tree[node])==1 and node!=root:
                dp[node]=[(1,node)]
                if count>0:
                    broke=True;break
            else:
                if len(tree[node])==2 and node!=root:
                    for s in tree[node]:
                        if dd[s]>dd[node]:
                            dp[node]=dp[s].copy()
                    if count>len(dp[node]):
                        broke=True;break
                    elif count==0:
                        dp[node].insert(0,(1,node))
                    else:
                        dp[node].insert(nums[node],(dp[node][nums[node]-1][0]+1,node))
                    for s in range(nums[node]+1,len(dp[node])):
                        dp[node][s]=(dp[node][s][0]+1,dp[node][s][1])
                else:
                    merge=[];new=[]
                    for s in tree[node]:
                        if dd[s]>dd[node]:
                            merge.append(dp[s].copy())
                    new=merge.pop()
                    while len(merge)>0:
                        temp=[];nxt=merge.pop()
                        new.reverse();nxt.reverse()
                        while len(new)>0 or len(nxt)>0:
                            if len(new)>0 and len(nxt)>0:
                                if new[-1][0]<=nxt[-1][0]:
                                    temp.append(new.pop())
                                else:
                                    temp.append(nxt.pop())
                            else:
                                if len(new)>0:
                                    temp.append(new.pop())
                                else:
                                    temp.append(nxt.pop())
                        new=temp.copy();temp=[]
                    dp[node]=new
                    if count>len(dp[node]):
                        broke=True;break
                    elif count==0:
                        dp[node].insert(0,(1,node))
                    else:
                        dp[node].insert(nums[node],(dp[node][nums[node]-1][0]+1,node))
                    for s in range(nums[node]+1,len(dp[node])):
                        dp[node][s]=(dp[node][s][0]+1,dp[node][s][1])
            if broke==True:
                break
        if broke==True:
            break
        cv-=1
    if broke==True:
        print("NO")
    else:
        print("YES")
        ans=[0 for s in range(n)]
        for s in dp[root]:
            ans[s[1]]=s[0]
        print(*ans)