#include <bits/stdc++.h>   template <class C, class E>   inline bool contains(const C& container, const E& element) {     return container.find(element) != container.end();   }   template <class T>   inline void checkmin(T& a, T b) {     if (b < a) a = b;   }   template <class T>   inline void checkmax(T& a, T b) {     if (b > a) a = b;   }   using namespace std;   class UnionFind {    public:     UnionFind(int elements) : _subsets(elements), _setCount(elements) {       for (int i = 0; i < elements; ++i) {         _subsets[i].parent = i;         _subsets[i].rank = 0;       }     }     int Find(int i) {       if (_subsets[i].parent != i) _subsets[i].parent = Find(_subsets[i].parent);       return _subsets[i].parent;     }     void Union(int x, int y) {       int xroot = Find(x);       int yroot = Find(y);       if (xroot == yroot) return;       --_setCount;       if (_subsets[xroot].rank < _subsets[yroot].rank)         _subsets[xroot].parent = yroot;       else if (_subsets[xroot].rank > _subsets[yroot].rank)         _subsets[yroot].parent = xroot;       else {         _subsets[yroot].parent = xroot;         _subsets[xroot].rank++;       }     }     struct subset {       int parent;       int rank;     };     void Trace() {       for (int i = (0), _b = ((_subsets.size()) - 1); i <= _b; i++)         cout << i <<  :  << Find(i) <<   | ;       cout << endl;     }     vector<subset> _subsets;     int _setCount;   };   struct SetInfo {     set<int> _yc;     set<int> _xc;   };   int main() {     ios_base::sync_with_stdio(false);     cin.tie(NULL);     cout.tie(NULL);     cout << std::setprecision(15);     cout << std::fixed;     long long xs, ys, q;     cin >> xs >> ys >> q;     UnionFind uf(xs + ys);     vector<pair<int, int> > p(q);     for (int i = (0), _b = ((q)-1); i <= _b; i++) {       int x, y;       cin >> p[i].first >> p[i].second;       --p[i].first;       --p[i].second;       uf.Union(p[i].first, xs + p[i].second);     }     map<int, SetInfo> ss;     for (int i = (0), _b = ((q)-1); i <= _b; i++) {       int id = uf.Find(p[i].first);       SetInfo& setInfo = ss[id];       setInfo._xc.insert(p[i].first);       setInfo._yc.insert(p[i].second);     }     long long got = 0;     long long totX = 0, totY = 0;     for (auto& p : ss) {       totX += (long long)p.second._xc.size();       totY += (long long)p.second._yc.size();     }     long long remX = xs - totX;     long long remY = ys - totY;     long long res = remX + remY - 1 + ss.size();     cout << res;     return 0;   }   