#include <bits/stdc++.h>
struct heapCmp {
  bool operator()(int i, int j) { return i > j; }
};
template <typename T>
bool cmp(T x, T y) {
  return x > y;
}
using namespace std;
const int MAX = 1e5 + 5;
const long long int mod = 1e9 + 7;
long long int modTwo[MAX];
map<long long int, long long int> X, lastX, Y, lastY;
vector<pair<long long int, long long int> > P;
void pre() {
  modTwo[0] = 1;
  for (long long int i = 1; i < MAX; i++) {
    modTwo[i] = (modTwo[i - 1] * 2) % mod;
  }
}
vector<long long int> G[MAX];
bool visit[MAX];
void dfs(int u, int &isCycle, int par, long long int &cnt) {
  if (visit[u]) {
    isCycle = 1;
    return;
  }
  visit[u] = 1;
  if (X.find(P[u].first) == X.end()) {
    cnt += 1;
  }
  X[P[u].first] = 1;
  if (Y.find(P[u].second) == Y.end()) {
    cnt += 1;
  }
  Y[P[u].second] = 1;
  for (auto v : G[u]) {
    if (v != par) dfs(v, isCycle, u, cnt);
  }
}
int main() {
  long long int n;
  scanf("%lld", &n);
  P.resize(n);
  pre();
  for (auto i = 0; i < n; i++) {
    scanf("%lld", &P[i].first);
    scanf("%lld", &P[i].second);
  }
  for (int i = 0; i < n; i++) {
    if (lastX.find(P[i].first) != lastX.end()) {
      G[i].push_back(lastX[P[i].first]);
      G[lastX[P[i].first]].push_back(i);
    }
    lastX[P[i].first] = i;
    if (lastY.find(P[i].second) != lastY.end()) {
      G[i].push_back(lastY[P[i].second]);
      G[lastY[P[i].second]].push_back(i);
    }
    lastY[P[i].second] = i;
  }
  int comp = 1, isCycle = 0;
  long long int ans = 1;
  for (int i = 0; i < n; i++) {
    isCycle = 0;
    long long int cnt = 0;
    if (!visit[i]) {
      dfs(i, isCycle, i, cnt);
      if (isCycle) {
        ans = (ans * modTwo[cnt]) % mod;
      } else {
        ans = (ans * (modTwo[cnt] - 1)) % mod;
        if (ans < 0) ans += mod;
      }
      comp += 1;
    }
  }
  cout << ans << "\n";
  return 0;
}
