#include <bits/stdc++.h>
using namespace std;
const int MAXN = 5 + 200000;
vector<int> filas[MAXN];
vector<int> columnas[MAXN];
struct dsu {
  vector<int> parent, sz;
  dsu(int n) {
    sz.assign(n, 1);
    parent.assign(n, 0);
    for (int i = (int)1; i < (int)n; ++i) parent[i] = i;
  }
  int find_parent(int k) {
    return parent[k] == k ? k : parent[k] = find_parent(parent[k]);
  }
  void join(int i, int j) {
    int p = find_parent(i), q = find_parent(j);
    if (p == q) return;
    if (sz[q] > sz[p]) swap(p, q);
    sz[p] += sz[q];
    parent[q] = p;
  }
  bool connected(int i, int j) { return find_parent(i) == find_parent(j); }
};
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int N, M, Q;
  cin >> N >> M >> Q;
  dsu d(1 + M);
  while (Q--) {
    int x, y;
    cin >> x >> y;
    filas[x].push_back(y);
    columnas[y].push_back(x);
  }
  for (int i = 1; i <= N; ++i)
    for (int j = 1; j < (int)filas[i].size(); ++j)
      d.join(filas[i][j], filas[i][j - 1]);
  for (int i = 1; i <= M; ++i) {
    for (int j = 1; j < (int)columnas[i].size(); ++j)
      d.join(filas[columnas[i][j]][0], filas[columnas[i][j - 1]][0]);
  }
  int need = 0;
  for (int i = 1; i <= N; ++i)
    if (filas[i].empty()) ++need;
  set<int> s;
  for (int i = 1; i <= M; ++i) s.insert(d.find_parent(i));
  cout << (int)s.size() - 1 + need;
  return 0;
}
