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
#include <bits/stdc++.h>
struct Avl {
  struct Node;
  using Node_ptr = std::shared_ptr<Node>;
  struct Node {
   public:
    int key;
    Node_ptr left;
    Node_ptr right;
    int height;
    int size;
  };
  Node_ptr root;
  Avl() : root(nullptr) {}
  int height(Node_ptr N) {
    if (N == nullptr) return 0;
    return N->height;
  }
  int Size(Node_ptr N) {
    if (N == nullptr) return 0;
    return N->size;
  }
  int size() { return Size(root); }
  int operator[](int index) {
    Node_ptr node = root;
    while (true) {
      if (Size(node->left) == index) {
        return node->key;
      } else if (index < Size(node->left)) {
        node = node->left;
      } else {
        index -= 1 + Size(node->left);
        node = node->right;
      }
    }
  }
  Node_ptr newNode(int key) {
    Node_ptr node = std::make_shared<Node>();
    node->key = key;
    node->left = nullptr;
    node->right = nullptr;
    node->height = 1;
    node->size = 1;
    return (node);
  }
  Node_ptr rightRotate(Node_ptr y) {
    Node_ptr x = y->left;
    Node_ptr T2 = x->right;
    int x_size = Size(x);
    int y_size = Size(y);
    int T1_size = Size(x->left);
    x->right = y;
    y->left = T2;
    y->height = std::max(height(y->left), height(y->right)) + 1;
    x->height = std::max(height(x->left), height(x->right)) + 1;
    x->size = y_size;
    y->size = y_size - T1_size - 1;
    return x;
  }
  Node_ptr leftRotate(Node_ptr x) {
    Node_ptr y = x->right;
    Node_ptr T2 = y->left;
    int x_size = Size(x);
    int y_size = Size(y);
    int T3_size = Size(y->right);
    y->left = x;
    x->right = T2;
    x->height = std::max(height(x->left), height(x->right)) + 1;
    y->height = std::max(height(y->left), height(y->right)) + 1;
    y->size = x_size;
    x->size = x_size - T3_size - 1;
    return y;
  }
  int getBalance(Node_ptr N) {
    if (N == nullptr) return 0;
    return height(N->left) - height(N->right);
  }
  void insert(int key) { root = insert_(root, key); }
  Node_ptr insert_(Node_ptr node, int key) {
    if (node == nullptr) return (newNode(key));
    if (key < node->key)
      node->left = insert_(node->left, key);
    else if (key > node->key)
      node->right = insert_(node->right, key);
    else
      return node;
    node->height = 1 + std::max(height(node->left), height(node->right));
    node->size = 1 + Size(node->left) + Size(node->right);
    int balance = getBalance(node);
    if (balance > 1 && key < node->left->key) return rightRotate(node);
    if (balance < -1 && key > node->right->key) return leftRotate(node);
    if (balance > 1 && key > node->left->key) {
      node->left = leftRotate(node->left);
      return rightRotate(node);
    }
    if (balance < -1 && key < node->right->key) {
      node->right = rightRotate(node->right);
      return leftRotate(node);
    }
    return node;
  }
  void erase(int key) { root = deleteNode_(root, key); }
  Node_ptr minValueNode(Node_ptr node) {
    Node_ptr current = node;
    while (current->left != nullptr) current = current->left;
    return current;
  }
  Node_ptr deleteNode_(Node_ptr root, int key) {
    if (root == nullptr) return root;
    if (key < root->key)
      root->left = deleteNode_(root->left, key);
    else if (key > root->key)
      root->right = deleteNode_(root->right, key);
    else {
      if ((root->left == nullptr) || (root->right == nullptr)) {
        Node_ptr temp = root->left ? root->left : root->right;
        if (temp == nullptr) {
          temp = root;
          root = nullptr;
        } else
          *root = *temp;
      } else {
        Node_ptr temp = minValueNode(root->right);
        root->key = temp->key;
        root->right = deleteNode_(root->right, temp->key);
      }
    }
    if (root == nullptr) return root;
    root->height = 1 + std::max(height(root->left), height(root->right));
    root->size = 1 + Size(root->left) + Size(root->right);
    int balance = getBalance(root);
    if (balance > 1 && getBalance(root->left) >= 0) return rightRotate(root);
    if (balance > 1 && getBalance(root->left) < 0) {
      root->left = leftRotate(root->left);
      return rightRotate(root);
    }
    if (balance < -1 && getBalance(root->right) <= 0) return leftRotate(root);
    if (balance < -1 && getBalance(root->right) > 0) {
      root->right = rightRotate(root->right);
      return leftRotate(root);
    }
    return root;
  }
  void preOrder() { preOrder_(root); }
  void preOrder_(Node_ptr root_) {
    if (root_ != nullptr) {
      preOrder_(root_->left);
      std::cout << root_->key << "(" << Size(root_) << ") ";
      preOrder_(root_->right);
    }
  }
};
struct Graph {
  size_t size;
  std::vector<std::vector<int>> children;
  std::vector<bool> used;
  Graph(size_t size) : size(size), children(size) {}
  void add_edge(int a, int b) {
    children[a].push_back(b);
    children[b].push_back(a);
  }
};
struct Dfs {
  const Graph& graph;
  std::vector<bool> used;
  std::function<void(int)> on_discover;
  std::function<void(int)> on_exit;
  std::function<void()> on_component;
  Dfs(const Graph& graph) : graph(graph), used(graph.size, false) {}
  void process() {
    for (int vertex = 0; vertex < graph.size; ++vertex) {
      if (!used[vertex]) {
        if (on_component) on_component();
        process(vertex);
      }
    }
  }
  void process(int vertex) {
    used[vertex] = true;
    if (on_discover) on_discover(vertex);
    for (const auto& child : graph.children[vertex]) {
      if (!used[child]) {
        process(child);
      }
    }
    if (on_exit) on_exit(vertex);
  }
};
template <class T>
std::vector<T> ReadVector(size_t size) {
  std::vector<T> vector(size);
  for (auto& element : vector) {
    std::cin >> element;
  }
  return vector;
}
int64_t divisor(int64_t x) {
  for (int64_t d = 2; d * d <= x; ++d) {
    while (x % d == 0) {
      x /= d;
      return d;
    }
  }
  return x;
}
void YES(bool yes) {
  if (yes) {
    std::cout << "YES\n";
  } else {
    std::cout << "NO\n";
  }
}
class Solver {
 public:
  Solver() {}
  void solve() {
    int n;
    std::cin >> n;
    ;
    Graph graph(n);
    int root = 0;
    std::vector<int> cs(n);
    for (int i = 0; i < n; ++i) {
      int p, c;
      std::cin >> p >> c;
      ;
      cs[i] = c;
      if (p == 0)
        root = i;
      else
        graph.add_edge(i, p - 1);
    }
    Avl avl;
    for (int i = 0; i < n; ++i) {
      avl.insert(i);
    }
    Dfs dfs(graph);
    int timer = 0;
    std::vector<int> discovered_at(n);
    std::vector<int> weight(n, 0);
    dfs.on_discover = [&timer, &discovered_at](int v) {
      discovered_at[v] = timer++;
    };
    dfs.on_exit = [&timer, &discovered_at, &weight](int v) {
      weight[v] = timer - discovered_at[v];
    };
    dfs.process(root);
    for (int i = 0; i < n; ++i)
      if (weight[i] - 1 < cs[i]) {
        YES(false);
        return;
      }
    Dfs dfs1(graph);
    std::vector<int> a(n);
    dfs1.on_discover = [&a, &cs, &avl](int v) {
      int csv = cs[v];
      if (csv >= avl.size())
        a[v] = -1;
      else {
        a[v] = avl[csv];
        avl.erase(avl[csv]);
      }
    };
    dfs1.process(root);
    if (*std::min_element(a.begin(), a.end()) < 0) {
      YES(false);
    } else {
      YES(true);
      for (int i = 0; i < n; ++i) std::cout << a[i] + 1 << " ";
    }
  }
};
int main() {
  Solver solver;
  solver.solve();
  return 0;
}
