#include <bits/stdc++.h>
#pragma comment(linker, "/STACK:16777216")
using namespace std;
inline int nextInt() {
  int s = 1, x = 0, c = getc(stdin);
  while (c <= 32) c = getc(stdin);
  if (c == '-') s = -1, c = getc(stdin);
  while ('0' <= c && c <= '9') x = x * 10 + c - '0', c = getc(stdin);
  return x * s;
}
inline void printInt(int x) {
  if (x < 0) putc('-', stdout), x = -x;
  char s[20];
  int n = 0;
  while (x || !n) s[n++] = '0' + x % 10, x /= 10;
  while (n--) putc(s[n], stdout);
}
inline void NextString(char *s) {
  int c = getc(stdin);
  while (c <= 32) c = getc(stdin);
  while (c > 32) *s++ = c, c = getc(stdin);
  *s = 0;
}
inline void writeWord(char *s) {
  while (*s) putchar(*s++);
}
struct edge {
  int xorsum, degree, numb;
  edge() {}
  edge(int xorsum, int degree, int numb) {
    this->xorsum = xorsum;
    this->degree = degree;
    this->numb = numb;
  }
};
int main() {
  int n;
  cin >> n;
  vector<edge> e(n);
  set<pair<int, int> > sol;
  queue<edge> q;
  for (int i = 0; i < n; ++i) {
    cin >> e[i].degree >> e[i].xorsum;
    e[i].numb = i;
    if (e[i].degree == 1) q.push(e[i]);
  }
  while (!q.empty()) {
    edge v = q.front();
    q.pop();
    e[v.xorsum].degree--;
    e[v.xorsum].xorsum ^= v.numb;
    sol.insert(make_pair(max(v.numb, v.xorsum), min(v.numb, v.xorsum)));
    if (e[v.xorsum].degree == 1) q.push(e[v.xorsum]);
  }
  cout << sol.size() << endl;
  for (set<pair<int, int> >::iterator it = sol.begin(); it != sol.end(); ++it) {
    cout << (*it).first << ' ' << (*it).second << endl;
  }
}
