#include #define rep(i,n) for(int i = 0; i < (n); i++) using namespace std; using ll = long long; using P = pair; struct UnionFind { vector par; UnionFind(int n) : par(n, -1) { } void init(int n) { par.assign(n, -1); } int root(int x) { if (par[x] < 0) return x; else return par[x] = root(par[x]); } bool same(int x, int y) { return root(x) == root(y); } bool merge(int x, int y) { x = root(x); y = root(y); if (x == y) return false; if (par[x] > par[y]) swap(x, y); // merge technique par[x] += par[y]; par[y] = x; return true; } int size(int x) { return -par[root(x)]; } }; int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int n, d, w; cin >> n >> d >> w; UnionFind uf1(n), uf2(n); rep(i,d){ int a, b; cin >> a >> b; a--, b--; uf1.merge(a, b); } rep(i,w){ int a, b; cin >> a >> b; a--, b--; uf2.merge(a, b); } vector> vec(n); rep(i,n){ vec[uf1.root(i)].insert(uf2.root(i)); } vector cnt(n); rep(i,n){ for(auto v : vec[i]){ cnt[i] += uf2.size(v); } } ll res = -n; rep(i,n) res += cnt[uf1.root(i)]; cout << res << endl; }