Typical tree recursion works. The key is: ANY node can be treated as the root, since it is about edge, not about node. This simplifies things a lot.
#include <cmath> #include <cstdio> #include <vector> #include <iostream> #include <algorithm> #include <unordered_set> using namespace std; typedef long long long64; struct Node { Node() :val(0){} Node(unsigned v) : val(v){} long64 val; unordered_set<int> inx; }; long64 ret = std::numeric_limits<unsigned>::max(); long64 go(vector<Node> &nodes, int root, long64 tsum) { Node &n = nodes[root]; long64 currsum = n.val; for (int i : n.inx) { nodes[i].inx.erase(root); currsum += go(nodes, i, tsum); } ret = std::min(std::abs(tsum - 2 * currsum), ret); return currsum; } int main() { int n; cin >> n; vector<Node> nodes(n); long64 sum = 0; for (int i = 0; i < n; i++) { unsigned v; cin >> v; sum += v; nodes[i].val = v; } for (int i = 0; i < n - 1; i++) { int pi, ci; cin >> pi >> ci; nodes[pi - 1].inx.insert(ci - 1); nodes[ci - 1].inx.insert(pi - 1); } go(nodes, 0, sum); cout << ret << endl; return 0; }