//#include<bits/stdc++.h>
#include<vector>
#include<iostream>
#include<algorithm>
#define ll long long
#define ldb long double
#define fi first
#define se second
#define sza(a) (int)a.size()
#define pir pair<int,int>
#define pirll pair<ll,ll>
using namespace std;
const int maxn = 2e5 + 5;

template <typename T> void maxi(T &x,T y){if (x < y) x = y;}

struct tree{
	int D[maxn],sz[maxn];
	ll R[maxn],V[maxn][2],child_cost[maxn],dp[maxn],maxR = 0;
	vector<int> vec[maxn];
	
	void add_edge(int u,int v){
		vec[u].push_back(v);
		vec[v].push_back(u);
	}
	
	void init_dfs(int u,int par){
		sz[u] = 1;
		if (u == 1) D[u] = 1;
		
		for (int v : vec[u])
		  if (v != par){
		  	D[v] = D[u] + 1;
		  	init_dfs(v,u);
		  	sz[u] += sz[v];
		  }
	}
	
	ll calc_self_cost(int n){
		ll cost = 0;
		for (int u = 1 ; u <= n ; u++)
		   cost += (ll)sz[u] * (ll)(n - sz[u]);
		return cost;
	}
	
	void child_cost_dfs(int u,int par){
		for (int v : vec[u])
		  if (v != par){
		  	child_cost_dfs(v,u);
		  	child_cost[u] += child_cost[v] + sz[v];
		  }
	}
	
	void reroot_dfs(int u,int par,ll cur){
		R[u] = child_cost[u] + cur;
		maxi(maxR,R[u]);
		
		for (int v : vec[u])
			if (v != par) cur += child_cost[v] + sz[v];
		
		for (int v : vec[u])
		    if (v != par)
		      reroot_dfs(v,u,cur - child_cost[v] - sz[v] + sz[1] - sz[v]);
	}
	
	void perform_reroot(int n){
		//->R : reroot
		child_cost_dfs(1,0);
		reroot_dfs(1,0,0);
	}
	
	void middle_dfs(int u,int par,ll S,int n,int n1,int n3,ll R1,ll R3){
		for (int v : vec[u])
		  if (v != par)
		     middle_dfs(v,u,S,n,n1,n3,R1,R3);
		
		V[u][0] = (ll)D[u] * S + R[u] * (ll)n1;
		V[u][1] = (ll)D[u] * S + R[u] * (ll)n3; 
		
		ll &f = dp[u];
		f = V[u][0] + V[u][1];
		
		for (int v : vec[u])if (v != par){
			maxi(f,V[u][0] + V[v][1]);
			maxi(f,V[u][1] + V[v][0]);
			
			maxi(V[u][0],V[v][0]);
			maxi(V[u][1],V[v][1]);
		}
		
		f -= 2*(ll)D[u] * S;
		
		f += (ll)(n + n1) * (ll)n3 + (ll)(n + n3) * (ll)n1;
		f += R3 * (ll)(n + n1);
		f += R1 * (ll)(n + n3);
	}
	
	ll middle_cost(int n,int n1,int n3,ll R1,ll R3){
	
		ll S = (ll)n1 * (ll)n3;
		
		middle_dfs(1,0,S,n,n1,n3,R1,R3);
		ll cost = 0;
		
		for (int u = 1 ; u <= n ; u++)
		  maxi(cost,dp[u]);
	
	    return cost;
	}
} tree[3];
int n[3];

void input_tree(){
	for (int i = 0 ; i < 3 ; i++){
		cin >> n[i];
		for (int m = 1 ; m < n[i] ; m++){
			int u,v;
			cin >> u >> v;
			tree[i].add_edge(u,v);
		}
	}
}

ll solve(){
	ll res = 0;
	int N = 3;
	
	for (int id = 0 ; id < N ; id++){
		tree[id].init_dfs(1,0);
		res += tree[id].calc_self_cost(n[id]);
	}
	
	for (int id = 0 ; id < N ; id++)
	  tree[id].perform_reroot(n[id]);
	
	ll tmp = 0;
	for (int id = 0 ; id < N ; id++){
		
		int i1 = (id + 1) % N,i2 = (id + 2) % N;
		ll R1 = tree[i1].maxR,R2 = tree[i2].maxR;
		
		tmp = max(tmp,tree[id].middle_cost(n[id],n[i1],n[i2],R1,R2)); //??additional cost)
	}
	
	res += tmp;
	return res;
}

int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	
	freopen("3cay.inp","r",stdin);
	freopen("3cay.ans","w",stdout);
	
	int stt;cin >> stt;
	
	input_tree();
	
	cout << solve();
	
	return 0;
}
