#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;   }   