#include <bits/stdc++.h>
using namespace std;
template <typename T>
using V = vector<T>;
const int MM = 5e5 + 5;
using T = long long;
bool QUERY;
struct Line {
  mutable T a, b, p;
  T Eval(T first) const { return a * first + b; }
  bool operator<(const Line& o) const { return QUERY ? p < o.p : a < o.a; }
};
struct ConvexHull : multiset<Line> {
  const T kInf = numeric_limits<T>::max();
  T div(T a, T b) { return a / b - ((a ^ b) < 0 && a % b); }
  bool isect(iterator first, iterator second) {
    if (second == end()) {
      first->p = kInf;
      return false;
    }
    if (first->a == second->a) {
      first->p = first->b > second->b ? kInf : -kInf;
    } else {
      first->p = div(second->b - first->b, first->a - second->a);
    }
    return first->p >= second->p;
  }
  void InsertLine(T a, T b) {
    auto nx = insert({a, b, 0}), it = nx++, pv = it;
    while (isect(it, nx)) {
      nx = erase(nx);
    }
    if (pv != begin() && isect(--pv, it)) {
      isect(pv, it = erase(it));
    }
    while ((it = pv) != begin() && (--pv)->p >= it->p) {
      isect(pv, erase(it));
    }
  }
  T EvalMax(T first) {
    if (empty()) {
      return -2e18;
    }
    QUERY = 1;
    auto it = lower_bound({0, 0, first});
    QUERY = 0;
    return it->Eval(first);
  }
};
vector<vector<int>> tree;
long long sub[MM];
long long n;
long long sq(long long e) { return e * e; }
void dfs1(int cur, int par) {
  sub[cur] = 1;
  for (auto u : tree[cur]) {
    if (u != par) {
      dfs1(u, cur);
      sub[cur] += sub[u];
    }
  }
}
long long dp1[MM];
void dfs2(int cur, int par) {
  dp1[cur] = sq(sub[cur]);
  for (int u : tree[cur]) {
    if (u != par) {
      dfs2(u, cur);
      dp1[cur] = min(dp1[cur], sq(sub[cur] - sub[u]) + dp1[u]);
    }
  }
}
vector<long long> ans;
void dfs3(int cur, int par) {
  ConvexHull CH;
  ans[cur] = sq(n);
  for (int u : tree[cur]) {
    if (u != par) {
      dfs3(u, cur);
      long long val = dp1[u] - CH.EvalMax(sub[u]) + sq(sub[u]);
      ans[cur] = min(ans[cur], val);
      ans[cur] = min(ans[cur], dp1[u] + sq(n - sub[u]));
      CH.InsertLine(2 * (n - sub[u]), -(dp1[u] + sq(n - sub[u])));
    }
  }
  return;
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  cin >> n;
  tree.resize(n);
  ans.resize(n);
  for (int i = 0; i < n - 1; i++) {
    int u, v;
    cin >> u >> v;
    u--;
    v--;
    tree[u].push_back(v);
    tree[v].push_back(u);
  }
  dfs1(0, -1);
  dfs2(0, -1);
  dfs3(0, -1);
  cout << (n * n - n) / 2 +
              (sq(n) - *min_element((ans).begin(), (ans).end())) / 2
       << endl;
  return 0;
}
