#include <bits/stdc++.h>
using namespace std;
template <typename T>
class Matrix {
 public:
  Matrix(std::size_t N, std::size_t M)
      : m_data(N * M, T()), m_rows(N), m_cols(M) {}
  inline T* operator[](int i) { return &m_data[i * m_cols]; }
  inline T const* operator[](int i) const { return &m_data[i * m_cols]; }
  inline std::size_t rows() const { return m_rows; }
  inline std::size_t cols() const { return m_cols; }

 private:
  std::vector<T> m_data;
  std::size_t m_rows;
  std::size_t m_cols;
};
template <typename T>
std::ostream& operator<<(std::ostream& os, const Matrix<T>& matrix) {
  for (std::size_t i = 0; i < matrix.rows(); ++i) {
    for (std::size_t j = 0; j < matrix.cols(); ++j) {
      os << std::left << std::setw(5) << matrix[i][j];
    }
    os << std::endl;
  }
  return os;
}
template <typename T>
void printV(const T& t) {
  std::copy(t.cbegin(), t.cend(),
            std::ostream_iterator<typename T::value_type>(std::cout, " "));
  cout << "\n";
}
template <typename T>
void printVV(const T& t) {
  for (int i = 0; i < t.size(); i++) {
    printf("%d: ", i);
    printV(t[i]);
  }
}
template <typename T, typename S>
void printVP(vector<pair<T, S>> vp) {
  if (vp.empty()) {
    cout << "\n";
    return;
  }
  for (int i = 0; i < vp.size() - 1; i++) {
    cout << "(" << vp[i].first << " " << vp[i].second << ") ";
  }
  cout << "(" << vp[vp.size() - 1].first << " " << vp[vp.size() - 1].second
       << ")\n";
}
template <typename T>
void printVVP(vector<vector<pair<T, T>>> vvp) {
  for (int i = 0; i < vvp.size(); i++) {
    cout << i << ": ";
    printVP(vvp[i]);
  }
}
vector<string> split(const string& s, char delim) {
  vector<string> result;
  stringstream ss(s);
  string item;
  while (getline(ss, item, delim)) {
    result.push_back(item);
  }
  return result;
}
bool is_number(const string& s) {
  string::const_iterator it = s.begin();
  while (it != s.end() && isdigit(*it)) ++it;
  return !s.empty() && it == s.end();
}
void fast() {
  ios::sync_with_stdio(false);
  cin.tie(NULL);
  cout.tie(NULL);
}
bool isValid(int r, int c, int R, int C) {
  return (r >= 0 && r < R && c >= 0 && c < C);
}
struct Can {
  long long x, r, id;
};
bool compareByX(const Can& lhs, const Can& rhs) { return lhs.x < rhs.x; }
class Person {
 public:
  string name, speak;
  unordered_set<string> understands;
  friend ostream& operator<<(ostream& os, const Person& p) {
    os << p.name << '(' << p.speak << "):";
    for (auto s : p.understands) os << " " << s;
    return os;
  }
};
vector<pair<int, int>> deltas = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
vector<int> numDays = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
vector<int> cumDays;
const int INF = 1e9 + 10;
const long long inf = 1e18 + 10;
const long double PI = 3.14159265359;
long long N;
vector<long long> deg;
vector<long long> X;
vector<pair<long long, long long>> edges;
queue<long long> q;
int main() {
  cin >> N;
  deg.assign(N, 0);
  X.assign(N, 0);
  for (int i = 0; i < (N); ++i) {
    cin >> deg[i] >> X[i];
    if (deg[i] == 1) {
      q.push(i);
    }
  }
  while (!q.empty()) {
    long long cur = q.front();
    q.pop();
    if (deg[cur] == 0) {
      continue;
    }
    long long nbr = X[cur];
    edges.push_back({cur, nbr});
    deg[cur]--;
    deg[nbr]--;
    X[nbr] ^= cur;
    if (deg[nbr] == 1) {
      q.push(nbr);
    }
  }
  cout << edges.size() << "\n";
  for (auto& p : edges) {
    cout << p.first << " " << p.second << "\n";
  }
}
