#include <bits/stdc++.h>
using namespace std;
const long long N = 1e6 + 7, M = 1000000007, inf = INT_MAX;
const long long INF = LLONG_MAX;
long long n, Q;
vector<long long> vec[N], v2[N];
long long par[N], sz[N];
void build() {
  for (long long i = 0; i < (long long)N; i++) {
    par[i] = i;
    sz[i] = 1;
  }
}
long long find(long long a) {
  if (par[a] == a) return a;
  return par[a] = find(par[a]);
}
void make_union(long long a, long long b) {
  long long pa = find(a);
  long long push_back = find(b);
  if (pa != push_back) {
    if (sz[pa] < sz[push_back]) swap(pa, push_back);
    par[push_back] = pa;
    sz[pa] += sz[push_back];
  }
}
bool vis[N];
void solve() {
  long long n, m;
  cin >> n >> m >> Q;
  build();
  for (long long i = 0; i < (long long)Q; i++) {
    long long r, c;
    cin >> r >> c;
    vec[c].push_back(r);
    v2[r].push_back(c);
    vis[r] = 1;
  }
  long long r1 = 0;
  for (long long i = 1; i < (long long)n + 1; i++)
    if (!vis[i]) r1++;
  for (long long i = 1; i < (long long)m + 1; i++) {
    for (long long j = 1; j < (long long)vec[i].size(); j++)
      make_union(vec[i][j], vec[i][j - 1]);
  }
  map<long long, vector<long long>> mp;
  for (long long i = 1; i < (long long)n + 1; i++) {
    mp[find(i)].push_back(i);
  }
  set<long long> st;
  for (long long i = 1; i < (long long)m + 1; i++) st.insert(i);
  long long cnt = mp.size();
  for (auto &it : mp) {
    for (auto &j : it.second) {
      for (auto k : v2[j]) st.erase(k);
    }
    cout << '\n';
  }
  cout << (cnt - 1) + st.size() << '\n';
}
int32_t main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  long long test = 1;
  while (test--) solve();
}
