#include <bits/stdc++.h>
using namespace std;
struct fast_ios {
  fast_ios() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);
  };
} fast_ios_;
template <typename T>
istream &operator>>(istream &is, vector<T> &v) {
  for (auto &x : v) is >> x;
  return is;
}
template <typename T>
ostream &operator<<(ostream &os, vector<T> &v) {
  for (long long i = 0; i < v.size(); i++) {
    cout << v[i];
    if (i != v.size() - 1) cout << endl;
  };
  return os;
}
template <typename T>
void Out(T x) {
  cout << x << endl;
}
template <typename T1, typename T2>
void Ans(bool first, T1 y, T2 n) {
  if (first)
    Out(y);
  else
    Out(n);
}
using vec = vector<long long>;
using mat = vector<vec>;
using Pii = pair<long long, long long>;
using PiP = pair<long long, Pii>;
using PPi = pair<Pii, long long>;
using bools = vector<bool>;
using pairs = vector<Pii>;
const long long mod = 1000000007;
class CHT {
  using T = long long;
  T id = -1000000000000000000;
  struct line {
    T a, b;
    line(T a, T b) : a(a), b(b) {}
    T get(T x) { return a * x + b; }
  };
  struct node {
    line l;
    node *lch, *rch;
    node(line l) : l(l), lch(nullptr), rch(nullptr) {}
    ~node() {
      if (lch) delete lch;
      if (rch) delete rch;
    }
  };

 public:
  long long n;
  vector<T> pos;
  node *root;
  bool calcMax;
  CHT(vector<T> pos, bool calcMax = true)
      : n(pos.size()), pos(pos), root(nullptr), calcMax(calcMax) {}
  ~CHT() {
    if (root) delete (root);
  }
  node *modify(node *p, long long lb, long long ub, line &l) {
    if (!p) return new node(l);
    if (p->l.get(pos[lb]) >= l.get(pos[lb]) &&
        p->l.get(pos[ub]) >= l.get(pos[ub]))
      return p;
    if (p->l.get(pos[lb]) <= l.get(pos[lb]) &&
        p->l.get(pos[ub]) <= l.get(pos[ub])) {
      p->l = l;
      return p;
    }
    long long c = (lb + ub) / 2;
    if (p->l.get(pos[c]) < l.get(pos[c])) swap(p->l, l);
    if (p->l.get(pos[lb]) <= l.get(pos[lb]))
      p->lch = modify(p->lch, lb, c, l);
    else
      p->rch = modify(p->rch, c + 1, ub, l);
    return p;
  }
  T sub(node *p, long long lb, long long ub, long long t) {
    if (!p) return id;
    if (ub - lb == 0) return p->l.get(pos[t]);
    long long c = (lb + ub) / 2;
    if (t <= c)
      return max(p->l.get(pos[t]), sub(p->lch, lb, c, t));
    else
      return max(p->l.get(pos[t]), sub(p->rch, c + 1, ub, t));
  }
  void insert(T a, T b) {
    if (!calcMax) {
      a *= -1;
      b *= -1;
    };
    line l(a, b);
    root = modify(root, 0, n - 1, l);
  }
  T get(T x) {
    long long t = distance(pos.begin(), lower_bound(pos.begin(), pos.end(), x));
    assert(t < n && pos[t] == x);
    T res = sub(root, 0, n - 1, t);
    if (!calcMax) res *= -1;
    return res;
  }
};
struct edge {
  long long to, cost;
};
class Graph {
 public:
  long long N;
  vector<vector<edge>> G;
  vec par, sz, dp;
  Graph(long long N) : N(N) {
    G = vector<vector<edge>>(N, vector<edge>(0));
    par.resize(N);
    sz.resize(N);
    dp.resize(N);
  }
  void add_Directed_edge(long long from, long long to, long long cost = 1) {
    G[from].push_back(edge({to, cost}));
  }
  void add_Undirected_edge(long long v1, long long v2, long long cost = 1) {
    add_Directed_edge(v1, v2, cost);
    add_Directed_edge(v2, v1, cost);
  }
  void dfs_for_sz(long long v, long long p = -1) {
    par[v] = p;
    sz[v] = 1;
    for (auto e : G[v])
      if (e.to != p) {
        dfs_for_sz(e.to, v);
        sz[v] += sz[e.to];
      }
  }
  void dfs_for_dp(long long v) {
    dp[v] = sz[v] * sz[v];
    for (auto e : G[v])
      if (e.to != par[v]) {
        dfs_for_dp(e.to);
        long long second = sz[v] - sz[e.to];
        dp[v] = min(dp[v], second * second + dp[e.to]);
      }
  }
  long long calcS(long long v) {
    long long S = (N - 1) * (N - 1) + 1;
    vec vs;
    set<long long> ss;
    for (auto e : G[v])
      if (e.to != par[v]) {
        long long second = N - sz[e.to];
        S = min(S, second * second + dp[e.to]);
        vs.push_back(e.to);
        ss.insert(sz[e.to]);
      }
    vec tmp;
    for (long long i : ss) tmp.push_back(i);
    if (((long long)vs.size()) >= 2) {
      CHT cht(tmp, false);
      for (long long i = (0); i < (((long long)vs.size())); i++) {
        long long j = vs[i];
        if (i > 0) S = min(S, sz[j] * sz[j] + dp[j] + cht.get(sz[j]));
        cht.insert(-2 * (N - sz[j]), (N - sz[j]) * (N - sz[j]) + dp[j]);
      }
    }
    return S;
  }
};
signed main() {
  long long n;
  cin >> n;
  Graph G(n);
  long long a, b;
  for (long long i = (0); i < (n - 1); i++) {
    cin >> a >> b;
    G.add_Undirected_edge(a - 1, b - 1, 1);
  }
  G.dfs_for_sz(0);
  G.dfs_for_dp(0);
  long long S = 1000000000000000000;
  for (long long i = (0); i < (n); i++) S = min(S, G.calcS(i));
  long long ans = n * (n - 1) / 2 + (n * n - S) / 2;
  Out(ans);
  return 0;
}
