#include <bits/stdc++.h>
#pragma comment(linker, "/stack:200000000")
#pragma GCC optimize("Ofast", "unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
using namespace std;
const long long inf = numeric_limits<long long>::max() / 2;
const long double eps = 1e-9;
const long double pi = acos(-1);
inline void solve(), read();
int main() {
  ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  read();
  solve();
  return 0;
}
struct graph {
  long long n;
  vector<vector<long long>> adj;
  graph() {}
  graph(long long n_) {
    n = n_;
    adj.resize(n);
  }
  void add(long long v, long long u) {
    adj[v].push_back(u);
    adj[u].push_back(v);
  }
};
const long long R = 1e9 + 7;
long long n;
vector<pair<long long, long long>> a;
map<long long, set<pair<long long, long long>>> mx, my;
graph g;
vector<long long> used;
set<long long> X, Y;
long long binpow(long long n, long long p) {
  n %= R;
  if (p == 0) {
    return 1;
  }
  if (p == 1) {
    return n % R;
  }
  long long ans = binpow(n, p / 2);
  ans = ans * ans % R;
  if (p % 2 == 1) {
    ans = ans * n % R;
  }
  return ans;
}
inline void build() {
  g = graph(n);
  for (long long i = 0; i < n; i++) {
    long long x = a[i].first, y = a[i].second;
    auto ix = mx[x].lower_bound({y, i});
    auto iy = my[y].lower_bound({x, i});
    if (ix != mx[x].end() && next(ix) != mx[x].end()) {
      g.add(i, next(ix)->second);
    }
    if (iy != my[y].end() && next(iy) != my[y].end()) {
      g.add(i, next(iy)->second);
    }
  }
}
long long cycle(long long v, long long p) {
  X.insert(a[v].first);
  Y.insert(a[v].second);
  used[v] = 1;
  long long ans = 0;
  for (long long u : g.adj[v]) {
    if (u == p) {
      continue;
    }
    if (used[u]) {
      ans = 1;
      continue;
    }
    if (cycle(u, v)) {
      ans = 1;
    }
  }
  return ans;
}
inline void solve() {
  build();
  long long ans = 1;
  used.assign(n, 0);
  for (long long i = 0; i < n; i++) {
    if (!used[i]) {
      X.clear(), Y.clear();
      bool ok = cycle(i, i);
      long long bp =
          binpow(2, (long long)((X).size()) + (long long)((Y).size()));
      if (ok) {
        ans *= bp;
      } else {
        ans *= (bp + R - 1) % R;
      }
      ans %= R;
    }
  }
  cout << ans << "\n";
}
inline void read() {
  cin >> n;
  a.resize(n);
  for (long long i = 0; i < n; i++) {
    cin >> a[i].first >> a[i].second;
    mx[a[i].first].insert({a[i].second, i});
    my[a[i].second].insert({a[i].first, i});
  }
}
