#include <bits/stdc++.h>
using namespace std;
template <class T>
constexpr inline int SZ(const T &x) {
  return x.size();
}
const char el = '\n';
static const int buf_size = 1 << 16;
static char buf[buf_size];
static int len = 0, pos = 0;
inline char getChar() {
  if (__builtin_expect(pos == len, 0))
    pos = 0, len = fread(buf, 1, buf_size, stdin);
  return buf[pos++];
}
template <typename T = int>
inline T read() {
  char s = 1, c = read<char>();
  T x = 0;
  if (c == '-') s = -1, c = getChar();
  while ('0' <= c && c <= '9') x = x * 10 + c - '0', c = getChar();
  return s == 1 ? x : -x;
}
template <>
inline char read<char>() {
  char c = getChar();
  while (c <= 32) c = getChar();
  return c;
}
template <>
inline string read<string>() {
  string s;
  for (char c = getChar(); c > ' '; c = getChar()) s += c;
  return s;
}
struct DSU {
  vector<int> e;
  DSU(int n) : e(n, -1) {}
  bool sameSet(int a, int b) { return find(a) == find(b); }
  int size(int x) { return -e[find(x)]; }
  int find(int x) { return e[x] < 0 ? x : e[x] = find(e[x]); }
  bool join(int a, int b) {
    a = find(a), b = find(b);
    if (a == b) return false;
    if (e[a] > e[b]) swap(a, b);
    e[a] += e[b];
    e[b] = a;
    return true;
  }
};
int32_t main() {
  ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
  cout << fixed << setprecision(13), cerr << fixed << setprecision(3);
  int n = read(), m = read(), q = read();
  vector<pair<int, int>> pts(q);
  for (auto &[y, x] : pts) {
    x = read() - 1, y = read() - 1;
  }
  sort(begin(pts), end(pts));
  DSU d(n);
  int ans = m - (q != 0);
  for (int i = 1; i < q; ++i)
    if (pts[i].first == pts[i - 1].first)
      d.join(pts[i].second, pts[i - 1].second);
    else
      ans--;
  bitset<(1 << 18)> bs{};
  for (int i = 0; i < n; ++i) bs[d.find(i)] = 1;
  ans += bs.count() - 1;
  cout << ans << el;
  return 0;
}
