#include <bits/stdc++.h>
using namespace std;
struct Coor {
  int x, y, id;
  Coor(int _x, int _y, int _id) {
    x = _x;
    y = _y;
    id = _id;
  }
  Coor() {}
};
int n;
int par[100005];
int siz[100005];
long long ans = 1;
long long pw[200005];
Coor c[100005];
set<int> sx[100005];
set<int> sy[100005];
bool cmp1(const Coor &a, const Coor &b) {
  return a.y != b.y ? a.y < b.y : a.x < b.x;
}
bool cmp2(const Coor &a, const Coor &b) {
  return a.x != b.x ? a.x < b.x : a.y < b.y;
}
void read() {
  cin >> n;
  for (int i = 1; i <= n; i++) {
    cin >> c[i].x >> c[i].y;
    c[i].id = i;
  }
}
void init_union_find() {
  for (int i = 1; i <= n; i++) {
    par[i] = i;
    siz[i] = 1;
  }
}
int find(int x) { return par[x] == x ? x : par[x] = find(par[x]); }
void unite(int x, int y) {
  int px = find(x);
  int py = find(y);
  if (px == py) return;
  siz[py] += siz[px];
  par[px] = py;
}
void build() {
  sort(c + 1, c + 1 + n, cmp1);
  for (int i = 1; i < n; i++) {
    if (c[i].y == c[i + 1].y) {
      unite(c[i].id, c[i + 1].id);
    }
  }
  sort(c + 1, c + 1 + n, cmp2);
  for (int i = 1; i < n; i++) {
    if (c[i].x == c[i + 1].x) {
      unite(c[i].id, c[i + 1].id);
    }
  }
}
void cal_pow() {
  pw[0] = 1;
  for (int i = 1; i < 200005; i++) pw[i] = (pw[i - 1] << 1ll) % 1000000007;
}
void cal_set() {
  for (int i = 1; i <= n; i++) {
    sx[find(c[i].id)].insert(c[i].x);
    sy[find(c[i].id)].insert(c[i].y);
  }
}
inline long long mod(long long x) {
  return (x % 1000000007 + 1000000007) % 1000000007;
}
void cal_ans() {
  for (int i = 1; i <= n; i++) {
    int fa = find(i);
    if (fa == i) {
      int edge = sx[fa].size() + sy[fa].size();
      if (siz[fa] >= edge)
        ans = mod(ans * mod(pw[edge]));
      else
        ans = mod(ans * mod(pw[edge] - 1));
    }
  }
}
void work() {
  init_union_find();
  build();
  cal_pow();
  cal_set();
  cal_ans();
  cout << ans << endl;
}
int main() {
  read();
  work();
}
