#include <bits/stdc++.h>
using namespace std;
struct UnionFind {
  int size;
  vector<int> parent;
  vector<int> v, e;
  UnionFind() {}
  UnionFind(int size) {
    this->size = size;
    parent.resize(size + 1);
    v.resize(size + 1);
    e.resize(size + 1);
    init();
  }
  void init() {
    for (int i = 0; i <= size; i++) parent[i] = i, v[i] = 1, e[i] = 0;
  }
  int root(int i) {
    if (parent[i] == i) return i;
    return parent[i] = root(parent[i]);
  }
  bool same(int i, int j) { return root(i) == root(j); }
  void unite(int i, int j) {
    int root_i = root(i), root_j = root(j);
    if (root_i == root_j) {
      e[root_i]++;
      return;
    }
    parent[root_i] = root_j;
    v[root_j] += v[root_i];
    e[root_j] += e[root_i] + 1;
  }
};
long long modpow(long long a, long long n) {
  if (n == 0) return 1;
  if (n % 2) {
    return ((a % 1000000007) * (modpow(a, n - 1) % 1000000007)) % 1000000007;
  } else {
    return modpow((a * a) % 1000000007, n / 2) % 1000000007;
  }
}
long long n;
long long x[100005], y[100005];
vector<long long> compX, compY;
UnionFind uf(200005);
void make(long long x[], vector<long long> &comp) {
  for (long long(i) = (1); (i) <= (n); (i)++) comp.push_back(x[i]);
  sort((comp).begin(), (comp).end());
  comp.erase(unique((comp).begin(), (comp).end()), comp.end());
  for (long long(i) = (1); (i) <= (n); (i)++)
    x[i] = lower_bound((comp).begin(), (comp).end(), x[i]) - comp.begin() + 1;
}
int main(void) {
  ios::sync_with_stdio(0);
  cin.tie(0);
  cin >> n;
  for (long long(i) = (1); (i) <= (n); (i)++) cin >> x[i] >> y[i];
  make(x, compX), make(y, compY);
  for (long long(i) = (1); (i) <= (n); (i)++) uf.unite(x[i], n + y[i]);
  long long ans = 1;
  for (long long(i) = (1); (i) <= (2 * n); (i)++) {
    if (uf.parent[i] != i) continue;
    if (uf.v[i] <= uf.e[i])
      ans *= modpow(2, uf.v[i]), ans %= 1000000007;
    else
      ans *= modpow(2, uf.v[i]) + 1000000007 - 1, ans %= 1000000007;
  }
  cout << ans << endl;
  return 0;
}
