#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; typedef long long ll; typedef unsigned int ui; const ll mod = 1000000007; const ll INF = (ll)1000000007 * 1000000007; typedef pair P; #define stop char nyaa;cin>>nyaa; #define rep(i,n) for(int i=0;i=0;i--) #define Rep(i,sta,n) for(int i=sta;i=sta;i--) #define rep1(i,n) for(int i=1;i<=n;i++) #define per1(i,n) for(int i=n;i>=1;i--) #define Rep1(i,sta,n) for(int i=sta;i<=n;i++) typedef long double ld; const ld eps = 1e-8; const ld pi = acos(-1.0); typedef pair LP; int dx[4]={1,-1,0,0}; int dy[4]={0,0,1,-1}; templatebool chmax(T &a, const T &b) {if(abool chmin(T &a, const T &b) {if(b par,ran; vector edge,size; int n; public: UnionFind(int x){ n=x; par.resize(n,0); ran.resize(n,0); edge.resize(n,0); size.resize(n,1); rep(i,n){ par[i]=i; } } int find(int x) { if (par[x]==x)return x; else return par[x]=find(par[x]); } void unite(int x, int y) { x=find(x),y=find(y); if (x==y){ edge[x]++; return; } if (ran[x] struct Compress{ vector V; Compress(){ V.clear(); } Compress(vector &V):V(V){} void add(T x){ V.push_back(x); } int build(){ sort(V.begin(),V.end()); V.erase(unique(V.begin(),V.end()),V.end()); return V.size(); } int get(T x){//get the index of the minimum element which is greater than x return lower_bound(V.begin(),V.end(),x)-V.begin(); } pair section(T l,T r){//get the range of indexes of [l,r) int l_=get(l),r_=get(r); return pair(l_,r_); } T &operator [] (int i) {return V[i];}; }; int n,d,w; P e[400010]; ll S[200010]; Compress comp1,comp2; map is_connected; void solve(){ cin >> n >> d >> w; UnionFind uf1(n),uf2(n); rep(i,d){ int a,b;cin >> a >> b;a--;b--; uf1.unite(a,b); e[i]=P(a,b); } rep(i,n){ comp1.add(uf1.find(i)); } rep(i,w){ int a,b;cin >> a >> b;a--;b--; uf2.unite(a,b); e[i+d]=P(a,b); } rep(i,n){ comp2.add(uf2.find(i)); } int Z=comp1.build();comp2.build(); rep(i,d+w){ int v=comp1.get(uf1.find(e[i].first)),u=comp2.get(uf2.find(e[i].second)); if(!is_connected[P(v,u)]) { is_connected[P(v,u)]=true; S[v]+=uf2.getSize(comp2[u]); } v=comp1.get(uf1.find(e[i].second)),u=comp2.get(uf2.find(e[i].first)); if(!is_connected[P(v,u)]) { is_connected[P(v,u)]=true; S[v]+=uf2.getSize(comp2[u]); } } rep(i,n){ int v=comp1.get(uf1.find(i)),u=comp2.get(uf2.find(i)); if(!is_connected[P(v,u)]) { is_connected[P(v,u)]=true; S[v]+=uf2.getSize(comp2[u]); } } ll ans=0; rep(i,Z){ //cout << i << " " << uf1.getSize(comp1[i]) << " " << S[i] << endl; ll T=uf1.getSize(comp1[i]); ans+=T*(S[i]-T); ans+=T*(T-1); } cout << ans << endl; } int main(){ ios::sync_with_stdio(false); cin.tie(0); cout << fixed << setprecision(50); solve(); }