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
import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

/*
Прокрастинирую
*/

public class Main {

    static FastReader in;
    static PrintWriter out;
    static Random rand = new Random();
    static final int INF = (int) (1e9);
    static final int MOD = (int) (1e9 + 7);
    static final int N = (int) (1e5 + 5);
    static int n;
    static int[] p, c;
    static ArrayList<Integer>[] g;
    static int[] size, ans;
    static SegmentTree st;

    static class SegmentTree {
        int n;
        int[] sum;

        SegmentTree(int[] a) {
            n = a.length;
            sum = new int[n * 4];
            build(a);
        }

        void build(int v, int tl, int tr, int[] a) {
            if (tl == tr) {
                sum[v] = a[tl];
            } else {
                int tm = (tl + tr) / 2;
                build(v * 2, tl, tm, a);
                build(v * 2 + 1, tm + 1, tr, a);
                sum[v] = sum[v * 2] + sum[v * 2 + 1];
            }
        }
        void build(int[] a) {
            build(1, 0, n - 1, a);
        }

        void upd(int v, int tl, int tr, int i, int val) {
            if (tl == tr) {
                sum[v] = val;
            } else {
                int tm = (tl + tr) / 2;
                if (i <= tm) {
                    upd(v * 2, tl, tm, i, val);
                } else {
                    upd(v * 2 + 1, tm + 1, tr, i, val);
                }
                sum[v] = sum[v * 2] + sum[v * 2 + 1];
            }
        }
        void upd(int i, int val) {
            upd(1, 0, n - 1, i, val);
        }

        int kth(int v, int tl, int tr, int k) {
            if (tl == tr) {
                return tl;
            }
            int tm = (tl + tr) / 2;
            if (k <= sum[v * 2]) {
                return kth(v * 2, tl, tm, k);
            } else {
                return kth(v * 2 + 1, tm + 1, tr, k - sum[v * 2]);
            }
        }
        int kth(int k) {
            if (k > sum[1]) {
                throw new IndexOutOfBoundsException();
            }
            return kth(1, 0, n - 1, k);
        }
    }

    static void dfs1(int v) {
        size[v] = 1;
        for (int u : g[v]) {
            dfs1(u);
            size[v] += size[u];
        }
    }

    static void dfs2(int v) {
        int x = c[v] + 1;
        ans[v] = st.kth(x) + 1;
        st.upd(ans[v] - 1, 0);
        for (int u : g[v]) {
            dfs2(u);
        }
    }

    static void solve() {
        n = in.nextInt();

        p = new int[n];
        c = new int[n];
        g = new ArrayList[n];
        Arrays.setAll(g, i -> new ArrayList<>());
        int root = 0;
        for (int i = 0; i < n; i++) {
            p[i] = in.nextInt();
            c[i] = in.nextInt();
            if (p[i] == 0) {
                root = i;
            } else {
                g[p[i] - 1].add(i);
            }
        }

        size = new int[n];
        dfs1(root);
        for (int i = 0; i < n; i++) {
            if (c[i] > size[i] - 1) {
                out.println("NO");
                return;
            }
        }

        int[] arr = new int[n];
        Arrays.fill(arr, 1);
        st = new SegmentTree(arr);
        ans = new int[n];
        dfs2(root);

        out.println("YES");
        for (int a : ans) {
            out.print(a);
            out.print(' ');
        }
        out.println();
    }

    public static void main(String[] args) throws FileNotFoundException {
        in = new FastReader(System.in);
//        in = new FastReader(new FileInputStream("input.txt"));
        out = new PrintWriter(System.out);
//        out = new PrintWriter(new FileOutputStream("output.txt"));


        int q = 1;

        while (q-- > 0) {
            solve();
        }

        out.close();
    }

    static class FastReader {
        BufferedReader br;
        StringTokenizer st;

        FastReader(InputStream is) {
            br = new BufferedReader(new InputStreamReader(is));
        }

        Integer nextInt() {
            return Integer.parseInt(next());
        }

        Long nextLong() {
            return Long.parseLong(next());
        }

        Double nextDouble() {
            return Double.parseDouble(next());
        }

        String next() {
            while (st == null || !st.hasMoreTokens()) {
                st = new StringTokenizer(nextLine());
            }
            return st.nextToken();
        }

        String nextLine() {
            String s = "";
            try {
                s = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return s;
        }
    }
}