Link to this code:
https://cses.fi/paste/e4741192aabc0338d9fdaa/#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MAX_N = 2e6 + 5;
int dp[MAX_N], sub_sz[MAX_N], N;
vector<int> tree[MAX_N]; // 1-based
void add_edge(int u, int v) {
tree[u].push_back(v);
tree[v].push_back(u);
}
// bottom to top
void dfs(int u, int p = -1) {
sub_sz[u] = 1;
for (int v : tree[u]) {
if (v == p) continue;
dfs(v, u);
sub_sz[u] += sub_sz[v];
// here dp is sum of all distances from the nodes in the subtree
dp[u] += dp[v] + sub_sz[v];
}
}
// top to bottom
void calc(int u, int par = -1) {
for (int v : tree[u]) {
if (v == par) continue;
dp[v] = dp[u] + N - 2 * sub_sz[v];
calc(v, u);
}
}
void solve() {
cin >> N;
for (int i = 0; i < N - 1; ++i) {
int u, v;
cin >> u >> v;
add_edge(u, v);
}
dfs(1);
calc(1);
// for (int i = 1; i <= N; ++i) cout << sub_sz[i] << ' ';
// cout << endl;
for (int i = 1; i <= N; ++i) cout << dp[i] << ' ';
}
int32_t main() {
solve();
return 0;
}
/*
call it rerooting or DP on trees or whatever
1. compute all the subtree sizes for each node
2. for each negihbour/child the sum of distances to all other nodes (dp[child])
S = sum of distances of parent to all other nodes (already computed dp[parent])
X = total nodes - nodes in child subtree = nodes - sub_sz[child]
Y = nodes in child subtree = sub_sz[child]
dp[child] = S + X - Y = dp[parent] + (nodes - sub_sz[child]) - sub_sz[child]
dp[child] = dp[parent] + nodes - 2 * sub_sz[child]
dp[v] = dp[u] + n - 2 * sub_sz[v]
(before entering into each child the dp values of parents should be already computed hence top down)
*/