Before reading the solution, recall the rerooting template:
Downward pass (DFS from root): Compute something for each subtree. What do you store? (Hint: Sum of distances and count of nodes in subtree)
Upward pass (reroot): When moving root from u to child v, how does v's answer change? (Hint: Nodes in v's subtree get closer, nodes outside get farther)
Final answer: Combine downward and upward information.
Try to write the two-pass structure: dfs1(u, parent) and dfs2(u, parent, up_value). What do you pass in up_value? Think for minute.