#include <bits/stdc++.h>   long long a[100][100];   using namespace std;   struct DynamicDisjointSetDS {     std::unordered_map<int, int> parent, degree;     int N;     DynamicDisjointSetDS(int n) { N = n; }     int getParent(int vertex) {       if (parent.find(vertex) != parent.end()) {         if (parent[vertex] != vertex) {           parent[vertex] = getParent(parent[vertex]);           return parent[vertex];         }       } else {         parent.insert(make_pair(vertex, vertex));         degree.insert(make_pair(vertex, 1));       }       return vertex;     }     void Union(int vertexA, int vertexB) {       int x = getParent(vertexA);       int y = getParent(vertexB);       if (x == y) return;       if (degree[x] > degree[y]) {         parent[y] = x;         degree[x] = degree[x] + degree[y];       } else {         parent[x] = y;         degree[y] = degree[y] + degree[x];       }     }     int GetTotalComponent() {       unordered_set<int> total;       for (auto itr = parent.begin(); itr != parent.end(); itr++) {         total.insert(getParent(itr->first));       }       return N - parent.size() + total.size();     }   };   int main() {     using namespace std;     long long n, m, q;     cin >> n >> m >> q;     unordered_set<long long> s, s2;     for (long long i = 1; i <= n; i++) {       s.insert(i);     }     for (long long i = 1; i <= m; i++) {       s2.insert(i);     }     DynamicDisjointSetDS ds(m + 1);     vector<vector<long long>> v(m + 1);     while (q--) {       long long r, c;       cin >> r >> c;       v[c].push_back(r);       s.erase(r);       s2.erase(c);     }     for (vector<long long> v2 : v) {       for (long long i = 1; i < v2.size(); i++) {         ds.Union(v2[i], v2[i - 1]);       }     }     unordered_set<long long> sc;     for (long long i = 1; i <= n; i++) {       sc.insert(ds.getParent(i));     }     cout << (s2.size() + sc.size() - 1) << endl;   }   