#include <bits/stdc++.h>
using namespace std;
void norm(vector<int *> &V) {
  vector<int> A;
  for (int *v : V) A.push_back(*v);
  sort(A.begin(), A.end());
  A.erase(unique(A.begin(), A.end()), A.end());
  for (int *v : V) *v = lower_bound(A.begin(), A.end(), *v) - A.begin();
}
struct DisjointSet {
  vector<int> P;
  DisjointSet(int N) : P(N, -1) {}
  int find(int x) { return P[x] < 0 ? x : (P[x] = find(P[x])); }
  bool join(int x, int y) {
    if ((x = find(x)) == (y = find(y))) return false;
    if (P[y] < P[x]) swap(x, y);
    P[x] += P[y];
    P[y] = x;
    return true;
  }
};
struct Point {
  int x, y;
  int X() { return x * 2; }
  int Y() { return y * 2 + 1; }
};
int modPow(int b, int e) {
  if (e == 0) return 1;
  int sq = modPow(b, e >> 1);
  sq = 1LL * sq * sq % 1000000007;
  if (e & 1) sq = 1LL * sq * b % 1000000007;
  return sq;
}
int main() {
  int N;
  scanf("%d", &N);
  vector<Point> V(N);
  vector<int *> X(N), Y(N);
  for (int i = 0; i < N; ++i) {
    scanf("%d%d", &V[i].x, &V[i].y);
    X[i] = &V[i].x;
    Y[i] = &V[i].y;
  }
  norm(X);
  norm(Y);
  DisjointSet DS(2 * N);
  set<int> S;
  for (int i = 0; i < N; ++i) {
    DS.join(V[i].X(), V[i].Y());
    S.insert(V[i].X());
    S.insert(V[i].Y());
  }
  vector<int> ESZ(2 * N);
  for (Point &p : V) {
    ESZ[DS.find(p.X())]++;
  }
  int ANS = 1;
  for (int u : S) {
    if (DS.find(u) != u) continue;
    int sz = -DS.P[u];
    int ec = ESZ[u];
    if (ec >= sz) {
      ANS = 1LL * ANS * modPow(2, sz) % 1000000007;
    } else {
      ANS = 1LL * ANS * (modPow(2, sz) - 1LL) % 1000000007;
    }
  }
  cout << ANS << endl;
}
