#include <bits/stdc++.h>
using namespace std;
int read() {
  int x = 0, flag = 1;
  char ch = getchar();
  while (!isdigit(ch) && ch != '-') ch = getchar();
  if (ch == '-') flag = -1, ch = getchar();
  while (isdigit(ch)) x = (x << 3) + (x << 1) + (ch - '0'), ch = getchar();
  return x * flag;
}
struct Edge {
  int to, next;
  Edge(int a = 0, int b = 0) { to = a, next = b; }
};
struct Tree {
  Edge l[100010 << 1];
  int n, cnt, pre, suf, ls, rs;
  int head[100010];
  long long ans, sum, cur, truns;
  long long dep[100010], siz[100010], sub[100010], d1[100010], d2[100010];
  vector<int> pac;
  void Add(int a, int b) {
    l[++cnt] = Edge(b, head[a]);
    head[a] = cnt;
  }
  void Pre(int u, int f) {
    siz[u] = 1;
    dep[u] = dep[f] + 1;
    for (int i = head[u]; i; i = l[i].next) {
      int v = l[i].to;
      if (v == f) continue;
      Pre(v, u);
      siz[u] += siz[v];
    }
  }
  void reroot(int tag, long long mv) {
    long long sub = siz[tag] * mv;
    long long out = (siz[tag] - siz[1]) * mv;
    cur += sub + out;
  }
  void Solve(int u, int f) {
    if (cur > ans) ans = cur;
    sum += cur;
    sub[u] = cur;
    for (int i = head[u]; i; i = l[i].next) {
      int v = l[i].to;
      if (v == f) continue;
      reroot(v, -1);
      Solve(v, u);
      reroot(v, 1);
    }
  }
  void Build() {
    for (int i = 1; i < n; ++i) {
      int a = read(), b = read();
      Add(a, b), Add(b, a);
    }
    Pre(1, 0);
    cur = sum = 0;
    for (int i = 1; i <= n; ++i) cur += dep[i] - 1;
    Solve(1, 0);
  }
  void find(int u, int f) {
    d1[u] = dep[u] * ls * rs + sub[u] * ls;
    d2[u] = dep[u] * ls * rs + sub[u] * rs;
    for (int i = head[u]; i; i = l[i].next) {
      int v = l[i].to;
      if (v == f) continue;
      find(v, u);
      truns = (truns > d1[u] + d2[v] - 2 * dep[u] * ls * rs
                   ? truns
                   : d1[u] + d2[v] - 2 * dep[u] * ls * rs);
      truns = (truns > d2[u] + d1[v] - 2 * dep[u] * ls * rs
                   ? truns
                   : d2[u] + d1[v] - 2 * dep[u] * ls * rs);
      d1[u] = (d1[u] > d1[v] ? d1[u] : d1[v]);
      d2[u] = (d2[u] > d2[v] ? d2[u] : d2[v]);
    }
  }
} T[3];
long long ans;
int b[3];
void Solve(Tree &t0, Tree &t1, Tree &t2) {
  t1.ls = t0.n;
  t1.rs = t2.n;
  t1.find(1, 0);
  ans = (ans > t1.truns + 1ll * (t0.ans + t0.n) * (t1.n + t2.n) +
                     1ll * (t2.ans + t2.n) * (t0.n + t1.n)
             ? ans
             : t1.truns + 1ll * (t0.ans + t0.n) * (t1.n + t2.n) +
                   1ll * (t2.ans + t2.n) * (t0.n + t1.n));
}
int main() {
  for (int i = 0; i <= 2; ++i) T[i].n = read();
  for (int i = 0; i <= 2; ++i) T[i].Build();
  for (int i = 0; i <= 2; ++i) b[i] = i;
  for (int i = 0; i <= 2; ++i) b[i] = i;
  for (int i = 0; i <= 2; ++i) Solve(T[(i + 2) % 3], T[i], T[(i + 1) % 3]);
  for (int i = 0; i <= 2; ++i) ans += T[i].sum / 2;
  printf("%I64d\n", ans);
  return 0;
}
