#include <bits/stdc++.h>
using namespace std;
long long gcd(long long a, long long b) { return b == 0 ? a : gcd(b, a % b); }
const int MAXN = 100000;
const int MOD = 1000000007;
int n;
int x[MAXN], y[MAXN];
int xx[MAXN], nxx;
int yy[MAXN], nyy;
int par[2 * MAXN], sz[2 * MAXN];
bool istree[2 * MAXN];
int find(int a) {
  if (par[a] == a) return a;
  return par[a] = find(par[a]);
}
void unite(int a, int b) {
  a = find(a), b = find(b);
  if (a == b) {
    istree[a] = false;
  } else {
    if (sz[a] < sz[b]) swap(a, b);
    par[b] = a, sz[a] += sz[b];
    if (!istree[b]) istree[a] = false;
  }
}
int p2[2 * MAXN + 1];
void run() {
  scanf("%d", &n);
  for (int i = (0); i < (n); ++i) scanf("%d%d", &x[i], &y[i]);
  nxx = 0;
  for (int i = (0); i < (n); ++i) xx[nxx++] = x[i];
  sort(xx, xx + nxx);
  nxx = unique(xx, xx + nxx) - xx;
  for (int i = (0); i < (n); ++i) x[i] = lower_bound(xx, xx + nxx, x[i]) - xx;
  nyy = 0;
  for (int i = (0); i < (n); ++i) yy[nyy++] = y[i];
  sort(yy, yy + nyy);
  nyy = unique(yy, yy + nyy) - yy;
  for (int i = (0); i < (n); ++i) y[i] = lower_bound(yy, yy + nyy, y[i]) - yy;
  for (int i = (0); i < (nxx + nyy); ++i)
    par[i] = i, sz[i] = 1, istree[i] = true;
  for (int i = (0); i < (n); ++i) unite(x[i], nxx + y[i]);
  p2[0] = 1;
  for (int i = (1); i <= (nxx + nyy); ++i)
    p2[i] = (long long)2 * p2[i - 1] % MOD;
  int ret = 1;
  for (int a = (0); a < (nxx + nyy); ++a)
    if (par[a] == a) {
      if (istree[a]) {
        ret = (long long)ret * (p2[sz[a]] + MOD - 1) % MOD;
      } else {
        ret = (long long)ret * p2[sz[a]] % MOD;
      }
    }
  printf("%d\n", ret);
}
int main() {
  run();
  return 0;
}
