Let's define a forest as a non-directed acyclic graph (also without loops and parallel edges). One day Misha played with the forest consisting of n vertices. For each vertex v from 0 to n - 1 he wrote down two integers, degreev and sv, were the first integer is the number of vertices adjacent to vertex v, and the second integer is the XOR sum of the numbers of vertices adjacent to v (if there were no adjacent vertices, he wrote down 0). 

Next day Misha couldn't remember what graph he initially had. Misha has values degreev and sv left, though. Help him find the number of edges and the edges of the initial graph. It is guaranteed that there exists a forest that corresponds to the numbers written by Misha.

Input

The first line contains integer n (1 ≤ n ≤ 216), the number of vertices in the graph.

The i-th of the next lines contains numbers degreei and si (0 ≤ degreei ≤ n - 1, 0 ≤ si < 216), separated by a space.

Output

In the first line print number m, the number of edges of the graph.

Next print m lines, each containing two distinct numbers, a and b (0 ≤ a ≤ n - 1, 0 ≤ b ≤ n - 1), corresponding to edge (a, b).

Edges can be printed in any order; vertices of the edge can also be printed in any order.

Examples

Input

3
2 3
1 0
1 0


Output

2
1 0
2 0


Input

2
1 1
1 0


Output

1
0 1

Note

The XOR sum of numbers is the result of bitwise adding numbers modulo 2. This operation exists in many modern programming languages. For example, in languages C++, Java and Python it is represented as "^", and in Pascal — as "xor".
#include <bits/stdc++.h>
using namespace std;
template <class T>
using rque = priority_queue<T, vector<T>, greater<T>>;
const long long mod = 998244353;
long long gcd(long long a, long long b) {
  long long c = a % b;
  while (c != 0) {
    a = b;
    b = c;
    c = a % b;
  }
  return b;
}
long long extGCD(long long a, long long b, long long &x, long long &y) {
  if (b == 0) {
    x = 1;
    y = 0;
    return a;
  }
  long long d = extGCD(b, a % b, y, x);
  y -= a / b * x;
  return d;
}
struct UnionFind {
  vector<long long> data;
  UnionFind(int sz) { data.assign(sz, -1); }
  bool unite(int x, int y) {
    x = find(x), y = find(y);
    if (x == y) return (false);
    if (data[x] > data[y]) swap(x, y);
    data[x] += data[y];
    data[y] = x;
    return (true);
  }
  int find(int k) {
    if (data[k] < 0) return (k);
    return (data[k] = find(data[k]));
  }
  long long size(int k) { return (-data[find(k)]); }
};
long long M = 1000000007;
vector<long long> fac(2000011);
vector<long long> ifac(2000011);
long long mpow(long long x, long long n) {
  long long ans = 1;
  while (n != 0) {
    if (n & 1) ans = ans * x % M;
    x = x * x % M;
    n = n >> 1;
  }
  return ans;
}
long long mpow2(long long x, long long n, long long mod) {
  long long ans = 1;
  while (n != 0) {
    if (n & 1) ans = ans * x % mod;
    x = x * x % mod;
    n = n >> 1;
  }
  return ans;
}
void setcomb() {
  fac[0] = 1;
  ifac[0] = 1;
  for (long long i = 0; i < 2000010; i++) {
    fac[i + 1] = fac[i] * (i + 1) % M;
  }
  ifac[2000010] = mpow(fac[2000010], M - 2);
  for (long long i = 2000010; i > 0; i--) {
    ifac[i - 1] = ifac[i] * i % M;
  }
}
long long comb(long long a, long long b) {
  if (a == 0 && b == 0) return 1;
  if (a < b || a < 0) return 0;
  long long tmp = ifac[a - b] * ifac[b] % M;
  return tmp * fac[a] % M;
}
long long perm(long long a, long long b) {
  if (a == 0 && b == 0) return 1;
  if (a < b || a < 0) return 0;
  return fac[a] * ifac[a - b] % M;
}
long long modinv(long long a) {
  long long b = M, u = 1, v = 0;
  while (b) {
    long long t = a / b;
    a -= t * b;
    swap(a, b);
    u -= t * v;
    swap(u, v);
  }
  u %= M;
  if (u < 0) u += M;
  return u;
}
long long modinv2(long long a, long long mod) {
  long long b = mod, u = 1, v = 0;
  while (b) {
    long long t = a / b;
    a -= t * b;
    swap(a, b);
    u -= t * v;
    swap(u, v);
  }
  u %= mod;
  if (u < 0) u += mod;
  return u;
}
template <int mod>
struct ModInt {
  int x;
  ModInt() : x(0) {}
  ModInt(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}
  ModInt &operator+=(const ModInt &p) {
    if ((x += p.x) >= mod) x -= mod;
    return *this;
  }
  ModInt &operator-=(const ModInt &p) {
    if ((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }
  ModInt &operator*=(const ModInt &p) {
    x = (int)(1LL * x * p.x % mod);
    return *this;
  }
  ModInt &operator/=(const ModInt &p) {
    *this *= p.inverse();
    return *this;
  }
  ModInt operator-() const { return ModInt(-x); }
  ModInt operator+(const ModInt &p) const { return ModInt(*this) += p; }
  ModInt operator-(const ModInt &p) const { return ModInt(*this) -= p; }
  ModInt operator*(const ModInt &p) const { return ModInt(*this) *= p; }
  ModInt operator/(const ModInt &p) const { return ModInt(*this) /= p; }
  bool operator==(const ModInt &p) const { return x == p.x; }
  bool operator!=(const ModInt &p) const { return x != p.x; }
  ModInt inverse() const {
    int a = x, b = mod, u = 1, v = 0, t;
    while (b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }
  ModInt pow(int64_t n) const {
    ModInt ret(1), mul(x);
    while (n > 0) {
      if (n & 1) ret *= mul;
      mul *= mul;
      n >>= 1;
    }
    return ret;
  }
  friend ostream &operator<<(ostream &os, const ModInt &p) { return os << p.x; }
  friend istream &operator>>(istream &is, ModInt &a) {
    int64_t t;
    is >> t;
    a = ModInt<mod>(t);
    return (is);
  }
  static int get_mod() { return mod; }
};
using mint = ModInt<mod>;
vector<vector<mint>> mul(vector<vector<mint>> a, vector<vector<mint>> b) {
  int i, j, k;
  mint t;
  int n = a.size(), m = b[0].size(), l = a[0].size();
  vector<vector<mint>> c(n, vector<mint>(m));
  for (i = 0; i < n; i++) {
    for (j = 0; j < m; j++) {
      t = 0;
      for (k = 0; k < l; k++) t += a[i][k] * b[k][j];
      c[i][j] = t;
    }
  }
  return c;
}
vector<vector<mint>> mat_pow(vector<vector<mint>> x, long long n) {
  long long k = x.size();
  vector<vector<mint>> ans(k, vector<mint>(k, 0));
  for (int i = 0; i < k; i++) ans[i][i] = 1;
  while (n != 0) {
    if (n & 1) ans = mul(ans, x);
    x = mul(x, x);
    n = n >> 1;
  }
  return ans;
}
int main() {
  long long n;
  cin >> n;
  long long d[n], s[n];
  for (long long i = 0; i < (n); i++) cin >> d[i] >> s[i];
  queue<long long> que;
  vector<pair<long long, long long>> ans;
  for (long long i = 0; i < (n); i++)
    if (d[i] == 1) que.push(i);
  while (!que.empty()) {
    long long now = que.front();
    que.pop();
    if (d[now] == 1) {
      ans.push_back(make_pair(now, s[now]));
      d[now]--;
      d[s[now]]--;
      s[s[now]] ^= now;
      if (d[s[now]] == 1) que.push(s[now]);
    }
  }
  cout << ans.size() << endl;
  for (long long i = 0; i < (ans.size()); i++)
    cout << ans[i].first << " " << ans[i].second << endl;
}
