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
# by the authority of GOD     author: manhar singh sachdev #

import os,sys
from io import BytesIO,IOBase

class SortedList:
    def __init__(self,iterable=None,_load=200):
        """Initialize sorted list instance."""
        if iterable is None:
            iterable = []
        values = sorted(iterable)
        self._len = _len = len(values)
        self._load = _load
        self._lists = _lists = [values[i:i+_load] for i in range(0,_len,_load)]
        self._list_lens = [len(_list) for _list in _lists]
        self._mins = [_list[0] for _list in _lists]
        self._fen_tree = []
        self._rebuild = True

    def _fen_build(self):
        """Build a fenwick tree instance."""
        self._fen_tree[:] = self._list_lens
        _fen_tree = self._fen_tree
        for i in range(len(_fen_tree)):
            if i|i+1<len(_fen_tree):
                _fen_tree[i|i+1] += _fen_tree[i]
        self._rebuild = False

    def _fen_update(self,index,value):
        """Update `fen_tree[index] += value`."""
        if not self._rebuild:
            _fen_tree = self._fen_tree
            while index<len(_fen_tree):
                _fen_tree[index] += value
                index |= index+1

    def _fen_query(self,end):
        """Return `sum(_fen_tree[:end])`."""
        if self._rebuild:
            self._fen_build()

        _fen_tree = self._fen_tree
        x = 0
        while end:
            x += _fen_tree[end-1]
            end &= end-1
        return x

    def _fen_findkth(self,k):
        """Return a pair of (the largest `idx` such that `sum(_fen_tree[:idx]) <= k`, `k - sum(_fen_tree[:idx])`)."""
        _list_lens = self._list_lens
        if k<_list_lens[0]:
            return 0,k
        if k>=self._len-_list_lens[-1]:
            return len(_list_lens)-1,k+_list_lens[-1]-self._len
        if self._rebuild:
            self._fen_build()

        _fen_tree = self._fen_tree
        idx = -1
        for d in reversed(range(len(_fen_tree).bit_length())):
            right_idx = idx+(1<<d)
            if right_idx<len(_fen_tree) and k>=_fen_tree[right_idx]:
                idx = right_idx
                k -= _fen_tree[idx]
        return idx+1,k

    def _delete(self,pos,idx):
        """Delete value at the given `(pos, idx)`."""
        _lists = self._lists
        _mins = self._mins
        _list_lens = self._list_lens

        self._len -= 1
        self._fen_update(pos,-1)
        del _lists[pos][idx]
        _list_lens[pos] -= 1

        if _list_lens[pos]:
            _mins[pos] = _lists[pos][0]
        else:
            del _lists[pos]
            del _list_lens[pos]
            del _mins[pos]
            self._rebuild = True

    def _loc_left(self,value):
        """Return an index pair that corresponds to the first position of `value` in the sorted list."""
        if not self._len:
            return 0,0

        _lists = self._lists
        _mins = self._mins

        lo,pos = -1,len(_lists)-1
        while lo+1<pos:
            mi = (lo+pos)>>1
            if value<=_mins[mi]:
                pos = mi
            else:
                lo = mi

        if pos and value<=_lists[pos-1][-1]:
            pos -= 1

        _list = _lists[pos]
        lo,idx = -1,len(_list)
        while lo+1<idx:
            mi = (lo+idx)>>1
            if value<=_list[mi]:
                idx = mi
            else:
                lo = mi

        return pos,idx

    def _loc_right(self,value):
        """Return an index pair that corresponds to the last position of `value` in the sorted list."""
        if not self._len:
            return 0,0

        _lists = self._lists
        _mins = self._mins

        pos,hi = 0,len(_lists)
        while pos+1<hi:
            mi = (pos+hi)>>1
            if value<_mins[mi]:
                hi = mi
            else:
                pos = mi

        _list = _lists[pos]
        lo,idx = -1,len(_list)
        while lo+1<idx:
            mi = (lo+idx)>>1
            if value<_list[mi]:
                idx = mi
            else:
                lo = mi

        return pos,idx

    def add(self,value):
        """Add `value` to sorted list."""
        _load = self._load
        _lists = self._lists
        _mins = self._mins
        _list_lens = self._list_lens

        self._len += 1
        if _lists:
            pos,idx = self._loc_right(value)
            self._fen_update(pos,1)
            _list = _lists[pos]
            _list.insert(idx,value)
            _list_lens[pos] += 1
            _mins[pos] = _list[0]
            if _load+_load<len(_list):
                _lists.insert(pos+1,_list[_load:])
                _list_lens.insert(pos+1,len(_list)-_load)
                _mins.insert(pos+1,_list[_load])
                _list_lens[pos] = _load
                del _list[_load:]
                self._rebuild = True
        else:
            _lists.append([value])
            _mins.append(value)
            _list_lens.append(1)
            self._rebuild = True

    def discard(self,value):
        """Remove `value` from sorted list if it is a member."""
        _lists = self._lists
        if _lists:
            pos,idx = self._loc_right(value)
            if idx and _lists[pos][idx-1]==value:
                self._delete(pos,idx-1)

    def remove(self,value):
        """Remove `value` from sorted list; `value` must be a member."""
        _len = self._len
        self.discard(value)
        if _len==self._len:
            raise ValueError('{0!r} not in list'.format(value))

    def pop(self,index=-1):
        """Remove and return value at `index` in sorted list."""
        pos,idx = self._fen_findkth(self._len+index if index<0 else index)
        value = self._lists[pos][idx]
        self._delete(pos,idx)
        return value

    def bisect_left(self,value):
        """Return the first index to insert `value` in the sorted list."""
        pos,idx = self._loc_left(value)
        return self._fen_query(pos)+idx

    def bisect_right(self,value):
        """Return the last index to insert `value` in the sorted list."""
        pos,idx = self._loc_right(value)
        return self._fen_query(pos)+idx

    def count(self,value):
        """Return number of occurrences of `value` in the sorted list."""
        return self.bisect_right(value)-self.bisect_left(value)

    def __len__(self):
        """Return the size of the sorted list."""
        return self._len

    def __getitem__(self,index):
        """Lookup value at `index` in sorted list."""
        pos,idx = self._fen_findkth(self._len+index if index<0 else index)
        return self._lists[pos][idx]

    def __delitem__(self,index):
        """Remove value at `index` from sorted list."""
        pos,idx = self._fen_findkth(self._len+index if index<0 else index)
        self._delete(pos,idx)

    def __contains__(self,value):
        """Return true if `value` is an element of the sorted list."""
        _lists = self._lists
        if _lists:
            pos,idx = self._loc_left(value)
            return idx<len(_lists[pos]) and _lists[pos][idx]==value
        return False

    def __iter__(self):
        """Return an iterator over the sorted list."""
        return (value for _list in self._lists for value in _list)

    def __reversed__(self):
        """Return a reverse iterator over the sorted list."""
        return (value for _list in reversed(self._lists) for value in reversed(_list))

    def __repr__(self):
        """Return string representation of sorted list."""
        return 'SortedList({0})'.format(list(self))

def dfs(root,path,ans,n):
    st = [root]
    nums = SortedList(range(1,n+1))
    lst = [-1]*n
    cou = 0
    val = [-1]*n
    if ans[st[-1]] >= len(nums):
        print('NO')
        return
    val[st[-1]-1] = nums[ans[st[-1]]]
    nums.discard(nums[ans[st[-1]]])
    lst[st[-1]-1] = cou
    cou += 1
    while len(st):
        if not len(path[st[-1]]):
            y,z = 0,st[-1]-1
            for j in range(n):
                if lst[j] > lst[z] and val[j] < val[z]:
                    y += 1
            if y != ans[z+1]:
                print('NO')
                return
            st.pop()
            continue
        st.append(path[st[-1]].pop())
        if ans[st[-1]] >= len(nums):
            print('NO')
            return
        val[st[-1]-1] = nums[ans[st[-1]]]
        nums.discard(nums[ans[st[-1]]])
        lst[st[-1]-1] = cou
        cou += 1
    if val.count(-1):
        print('NO')
    else:
        print('YES')
        print(*val)

def main():
    n = int(input())
    path = [[] for _ in range(n+1)]
    ans = [0]*(n+1)
    for i in range(1,n+1):
        p,c = map(int,input().split())
        if p:
            path[p].append(i)
        else:
            root = i
        ans[i] = c
    dfs(root,path,ans,n)

#Fast IO Region
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")

if __name__ == '__main__':
    main()