#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const long long LINF = 0x3f3f3f3f3f3f3f3f;
template <typename T, typename T2>
inline void _max(T &a, T2 b) {
  a = max((T)a, (T)b);
}
template <typename T, typename T2>
inline void _min(T &a, T2 b) {
  a = min((T)a, (T)b);
}
int MOD = int(1e9) + 7;
inline int add(const int a, const int b, const int mod = MOD) {
  return (a + b >= mod) ? (a + b - mod) : (a + b);
}
inline void _add(int &a, const int b, const int mod = MOD) {
  a = add(a, b, mod);
}
inline int sub(const int a, const int b, const int mod = MOD) {
  return (a - b < 0) ? (a - b + mod) : (a - b);
}
inline void _sub(int &a, const int b, const int mod = MOD) {
  a = sub(a, b, mod);
}
inline int neg(const int a, const int mod = MOD) { return mod - a; }
inline int mul(const int a, const int b, const int mod = MOD) {
  return (a * 1ll * b) % mod;
}
inline void _mul(int &a, const int b, const int mod = MOD) {
  a = mul(a, b, mod);
}
int binPow(int b, long long p, const int mod = MOD) {
  int r = 1;
  while (p) {
    if (p & 1) r = mul(r, b, mod);
    b = mul(b, b, mod);
    p >>= 1;
  }
  return r;
}
int gcdex(int a, int b, int &x, int &y) {
  if (!b) return x = 1, y = 0, a;
  int px, py, res = gcdex(b, a % b, px, py);
  return x = py, y = px - a / b * py, res;
}
int inv(const int a, const int mod = MOD) {
  int x, y;
  int g = gcdex(a, mod, x, y);
  assert(g == 1);
  x = (x % mod + mod) % mod;
  return x;
}
inline int dvd(const int a, const int b, const int mod = MOD) {
  int rev = inv(b, mod);
  return mul(a, inv(b, mod), mod);
}
inline void _dvd(int &a, const int b, const int mod = MOD) {
  a = dvd(a, b, mod);
}
inline int convert(int x, const int mod = MOD) {
  int tx = x % mod + mod;
  return tx >= mod ? tx - mod : tx;
};
struct mNum {
  int x, m;
  mNum(int _x, int m = MOD) : x(convert(_x, m)), m(m) {}
  mNum(long long _x, int m = MOD) : x(convert(_x, m)), m(m) {}
};
mNum operator+(mNum a, mNum b) { return mNum(add(a.x, b.x, a.m), a.m); }
mNum operator-(mNum a, mNum b) { return mNum(sub(a.x, b.x, a.m), a.m); }
mNum operator*(mNum a, mNum b) { return mNum(mul(a.x, b.x, a.m), a.m); }
mNum operator/(mNum a, mNum b) { return mNum(dvd(a.x, b.x, a.m), a.m); }
mNum operator^(mNum a, long long x) { return mNum(binPow(a.x, x, a.m), a.m); }
mNum operator+=(mNum &a, mNum b) { return a = a + b; }
mNum operator-=(mNum &a, mNum b) { return a = a - b; }
mNum operator*=(mNum &a, mNum b) { return a = a * b; }
mNum operator/=(mNum &a, mNum b) { return a = a / b; }
mNum operator^=(mNum &a, long long x) { return a = a ^ x; }
const int MAX = 1e5 + 10;
int n;
int x[MAX], y[MAX];
map<int, set<int>> gx, gy;
map<int, int> dx, dy;
set<int> usedx, usedy;
int f[MAX], rf[MAX];
void clear() {
  gx.clear(), gy.clear(), dx.clear(), dy.clear();
  usedx.clear(), usedy.clear();
}
void read() {
  for (int i = 0; i < n; i++) scanf("%d%d", &x[i], &y[i]);
}
int res = 1, nl, np;
void dfsy(int ty);
void dfsx(int tx) {
  usedx.insert(tx);
  nl++, np += gx[tx].size();
  for (auto ty : gx[tx]) {
    if (usedy.count(ty)) continue;
    dfsy(ty);
  }
}
void dfsy(int ty) {
  usedy.insert(ty);
  nl++;
  for (auto tx : gy[ty]) {
    if (usedx.count(tx)) continue;
    dfsx(tx);
  }
}
int C(int n, int k) {
  if (k < 0 || k > n) return 0;
  return mul(mul(f[n], rf[n - k]), rf[k]);
}
void solve() {
  set<int> ux, uy;
  for (int i = 0; i < n; i++) ux.insert(x[i]), uy.insert(y[i]);
  for (int i = 0; i < n; i++)
    gx[x[i]].insert(y[i]), gy[y[i]].insert(x[i]), dx[x[i]]++, dy[y[i]]++;
  res = 1;
  usedx.clear(), usedy.clear();
  for (auto &tx : ux) {
    if (usedx.count(tx)) continue;
    nl = 0, np = 0;
    dfsx(tx);
    int tmp = 0;
    for (int i = 0; i <= np; i++) _add(tmp, C(nl, i));
    _mul(res, tmp);
  }
  printf("%d\n", res);
}
void precalc() {
  f[0] = 1;
  for (int i = 1; i < MAX; i++) f[i] = mul(f[i - 1], i);
  for (int i = 0; i < MAX; i++) rf[i] = inv(f[i]);
}
int main() {
  precalc();
  while (scanf("%d", &n) == 1) {
    clear();
    read();
    solve();
    return 0;
  }
  return 0;
}
