#include <bits/stdc++.h>
using namespace std;
bool rows[200009], cols[200009];
bool uniqueParents[200009];
int parent[200009];
int depth[200009];
vector<pair<int, int>> indices;
void makeSets() {
  for (int i = 0; i < 200009; i++) {
    parent[i] = i;
    depth[i] = 1;
  }
}
int findSet(int v) {
  if (v == parent[v]) return v;
  return parent[v] = findSet(parent[v]);
}
void unionSet(int u, int v) {
  int a = findSet(u);
  int b = findSet(v);
  if (a != b) {
    if (depth[a] < depth[b]) swap(a, b);
    parent[b] = a;
    if (depth[a] == depth[b]) depth[a]++;
  }
}
int main() {
  makeSets();
  int n, m, q;
  cin >> n >> m >> q;
  for (int i = 0; i < q; i++) {
    int l, r;
    cin >> l >> r;
    indices.push_back(make_pair(l, r));
    rows[l] = true;
    cols[r] = true;
  }
  sort(indices.begin(), indices.end());
  for (int i = 1; i < q; i++)
    if (indices[i].first == indices[i - 1].first)
      unionSet(indices[i].second, indices[i - 1].second);
  int emptyRows = 0, emptyCols = 0;
  for (int i = 1; i <= n; i++) emptyRows += !rows[i];
  for (int i = 1; i <= m; i++) {
    if (!cols[i]) {
      emptyCols++;
      parent[i] = -1;
    }
  }
  int ans = max(emptyRows, emptyCols);
  int sets = min(emptyRows, emptyCols);
  for (int i = 1; i <= m; i++)
    if (parent[i] != -1 && !uniqueParents[findSet(i)]) {
      sets++;
      uniqueParents[findSet(i)] = true;
    }
  cout << sets + ans - 1 << endl;
}
