#include <bits/stdc++.h>
#pragma comment(linker, "/STACK:32000000")
const int nil = -1;
using namespace std;
inline bool read(int& val) { return scanf("%d", &val) != -1; }
inline bool read(double& val) { return scanf("%lf", &val) != -1; }
inline bool read(char* val) { return scanf("%s", val) != -1; }
template <class T1, class T2>
inline bool read(T1& a, T2& b) {
  return read(a) && read(b);
}
template <class T1, class T2, class T3>
inline bool read(T1& a, T2& b, T3& c) {
  return read(a) && read(b) && read(c);
}
template <class T1, class T2, class T3, class T4>
inline bool read(T1& a, T2& b, T3& c, T4& d) {
  return read(a) && read(b) && read(c) && read(d);
}
template <class T1, class T2, class T3, class T4, class T5>
inline bool read(T1& a, T2& b, T3& c, T4& d, T5& e) {
  return read(a) && read(b) && read(c) && read(d) && read(e);
}
const long long mod = 1000000007;
const int M = 31;
const int N = 411111;
long long pow(long long a, long long b, long long mod) {
  long long x = 1;
  for (; b != 0; b >>= 1, a = a * a % mod)
    if (b & 1) x = x * a % mod;
  return x;
}
struct merge_set {
  int P[N], C[N];
  void init(int n) {
    for (int i = 0, _ = (n); i < _; ++i) P[i] = i, C[i] = 1;
  }
  int find(int a) {
    int p = a;
    while (p != P[p]) p = P[p];
    for (int pa = P[a]; pa != p; a = pa, pa = P[a]) P[a] = p;
    return p;
  }
  int merge(int a, int b) {
    if (a == b || a != P[a] || b != P[b]) return -1;
    if (C[a] < C[b]) swap(a, b);
    P[b] = a;
    C[a] += C[b];
    C[b] = 0;
    return a;
  }
} S;
vector<int> X[N];
vector<int> Y[N];
set<int> cntx[N];
int cnt[N], cnty[N];
int px[N], py[N], xx[N], yy[N];
int main() {
  int n;
  read(n);
  for (int i = 0, _ = (n); i < _; ++i) {
    read(px[i], py[i]);
    xx[i] = px[i];
    yy[i] = py[i];
  }
  sort(xx, xx + n);
  sort(yy, yy + n);
  int nx = unique(xx, xx + n) - xx;
  int ny = unique(yy, yy + n) - yy;
  for (int i = 0, _ = (n); i < _; ++i) {
    px[i] = lower_bound(xx, xx + nx, px[i]) - xx;
    py[i] = lower_bound(yy, yy + ny, py[i]) - yy;
  }
  S.init(n);
  for (int i = 0, _ = (n); i < _; ++i) {
    X[py[i]].push_back(px[i]);
    Y[px[i]].push_back(py[i]);
  }
  for (int i = 0, _ = (nx); i < _; ++i)
    if (!Y[i].empty()) {
      int a = S.find(Y[i][0]);
      for (int j = (1), _ = (Y[i].size()); j < _; ++j) {
        a = S.find(a);
        int b = S.find(Y[i][j]);
        if (a != b) a = S.merge(a, b);
      }
    }
  for (int i = 0, _ = (ny); i < _; ++i) {
    int p = S.find(i);
    cnty[p]++;
    for (int j = 0, _ = (X[i].size()); j < _; ++j) {
      cntx[p].insert(X[i][j]);
      cnt[p]++;
    }
  }
  long long ans = 1;
  for (int i = 0, _ = (ny); i < _; ++i)
    if (cnt[i]) {
      int all = cntx[i].size() + cnty[i];
      int cur = pow(2, all, mod);
      if (cnt[i] < all) cur = (cur + mod - 1) % mod;
      ans = ans * cur % mod;
    }
  cout << ans << endl;
  return 0;
}
