#include <bits/stdc++.h>
const long long INF = 4e18L + 1;
const int IINF = 1e9 + 1;
using namespace std;
template <class TH>
void _dbg(const char* sdbg, TH h) {
  cerr << sdbg << '=' << h << endl;
}
template <class TH, class... TA>
void _dbg(const char* sdbg, TH h, TA... a) {
  while (*sdbg != ',') cerr << *sdbg++;
  cerr << '=' << h << ',';
  _dbg(sdbg + 1, a...);
}
const int N = 101000;
vector<int> v[N];
int odw[N];
vector<pair<int, int>> pts;
int dfs(int x, int ojc, set<int>& sx, set<int>& sy) {
  odw[x] = 1;
  sx.insert(pts[x].first);
  sy.insert(pts[x].second);
  int w = 1;
  for (auto y : v[x]) {
    if (!odw[y]) {
      w += dfs(y, x, sx, sy);
    }
  }
  return w;
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  const long long P = 1e9 + 7;
  vector<long long> pot2({1});
  for (long long i = (long long)0; i < (long long)N; i++) {
    pot2.push_back(pot2.back() * 2 % P);
  }
  int n;
  cin >> n;
  pts.resize(n);
  vector<pair<int, int>> sx, sy;
  for (long long i = (long long)0; i < (long long)n; i++) {
    cin >> pts[i].first >> pts[i].second;
    sx.push_back({pts[i].first, i});
    sy.push_back({pts[i].second, i});
  }
  sort((sx).begin(), (sx).end());
  sort((sy).begin(), (sy).end());
  for (long long i = (long long)1; i < (long long)n; i++) {
    if (sx[i - 1].first == sx[i].first) {
      v[sx[i - 1].second].push_back(sx[i].second);
      v[sx[i].second].push_back(sx[i - 1].second);
    }
    if (sy[i - 1].first == sy[i].first) {
      v[sy[i - 1].second].push_back(sy[i].second);
      v[sy[i].second].push_back(sy[i - 1].second);
    }
  }
  long long rez = 1;
  for (long long i = (long long)0; i < (long long)n; i++) {
    if (!odw[i]) {
      set<int> sx, sy;
      long long l = dfs(i, -1, sx, sy);
      long long k = (int)((sx).size()) + (int)((sy).size());
      (i, l, k);
      long long up = pot2[k];
      if (k > l) {
        up = (up + P - 1) % P;
      }
      rez = rez * up % P;
    };
  }
  cout << rez;
}
