#include using namespace std; #define rep(i, l, n) for(int i = int(l); i < int(n); i++) #define ll long long #define all(x) (x).begin(), (x).end() #define rall(x) (x).rbegin(), (x).rend() template bool chmin(T &a, T b) {if(a > b) {a = b; return true;} return false;} template bool chmax(T &a, T b) {if(a < b) {a = b; return true;} return false;} template using spq = priority_queue, greater>; // bool -> Yes/No string answer(bool b) {return b ? "Yes" : "No";} void fix(int k) {cout << fixed << setprecision(k);} const int inf = 2e9; const long long INF = 2e12; const long double eps = 1e-12; const long double pi = acos(-1); int dx[] = {0, -1, 0, 1, -1, -1, 1, 1}, dy[] = {1, 0, -1, 0, 1, -1, -1, 1}; struct UnionFind { int n, cur_size; vector data; UnionFind(int N) : n(N) { data.assign(n, -1); cur_size = n; } int root(int x) { assert(0 <= x && x < n); if(data[x] < 0) return x; else return data[x] = root(data[x]); } bool merge(int a, int b) { assert(0 <= a && a < n); assert(0 <= b && b < n); a = root(a); b = root(b); if(a == b) return false; if(data[a] > data[b]) swap(a, b); data[a] += data[b]; data[b] = a; cur_size--; return true; } bool same(int a, int b) { assert(0 <= a && a < n); assert(0 <= b && b < n); return root(a) == root(b); } int size(int x) { assert(0 <= x && x < n); return -data[root(x)]; } int size() { return cur_size; } vector> groups() { vector> member(n), ret; for(int i = 0; i < n; i++) { member[root(i)].emplace_back(i); } for(int i = 0; i < n; i++) { if(!member[i].empty()) ret.emplace_back(member[i]); } return ret; } }; void main_program() { int h, w; cin >> h >> w; int n; cin >> n; int a[n], b[n]; UnionFind uf(h + w); rep(i, 0, n) { cin >> a[i] >> b[i]; uf.merge(--a[i], --b[i] + h); } vector g = uf.groups(); int siz = g.size(); int dp[2][siz + 1][h + 1]; rep(i, 0, siz + 1) rep(j, 0, h + 1) { dp[0][i][j] = -1; dp[1][i][j] = inf; } dp[0][0][0] = dp[1][0][0] = 0; rep(i, 0, siz) { int cnt = 0; for(int u : g[i]) if(u < h) cnt++; rep(j, 0, h + 1) { if(dp[0][i][j] != -1) { chmax(dp[0][i + 1][j], dp[0][i][j]); chmax(dp[0][i + 1][j + cnt], dp[0][i][j] + int(g[i].size()) - cnt); } if(dp[1][i][j] != inf) { chmin(dp[1][i + 1][j], dp[0][i][j]); chmin(dp[1][i + 1][j + cnt], dp[0][i][j] + int(g[i].size()) - cnt); } } } int ans = 0; rep(i, 0, h + 1) { if(h - 2 * i >= 0 && dp[0][siz][i] != -1) { chmax(ans, i * w + dp[0][siz][i] * h - 2 * i * dp[0][siz][i]); } if(h - 2 * i < 0 && dp[1][siz][i] != inf) { chmax(ans, i * w + dp[1][siz][i] * h - 2 * i * dp[1][siz][i]); } } cout << ans << "\n"; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int T = 1; //cin >> T; while(T--) { main_program(); } }