
Problem Description
Find a point such that the total distance from all other points to it is minimized.
The calculation method for the total distance is: the sum of (each point’s population multiplied by its distance to the target point).
Note! This problem has no edge weights! Only node weights (I stumbled here the first time [facepalm]).
Approach
There are two methods: brute force and rerooting DP.
The brute force method is straightforward. Since is small, directly traverse each node from to as the root, perform a DFS to calculate the total distance, and take the minimum value.
Rerooting DP involves first performing a DFS to calculate the total distance with node as the root, then performing another DFS to calculate the total distance with other nodes as the root, and finally taking the minimum value.
So, what is the state transition equation?
Look at the graph in the problem. If the hospital is moved to node , doesn’t it mean that nodes and on the left have to travel farther, while nodes , , and on the right have to travel less?
Thus, the state transition equation can easily be derived as:
Done!
Code
// Brute force solution#include <iostream>#include <vector>#include <algorithm>using namespace std;vector <int> wth[105];int ans = 1e9, cnt[105], hz[105];int a[105];void dfs(int now, int f, int dep, int rt){ cnt[now] = hz[now]; a[rt] += hz[now] * dep; for(auto v : wth[now]) { if(v == f) { continue; } dfs(v, now, dep + 1, rt); cnt[now] += cnt[v]; }}int main(){ int n; cin >> n; for(int i = 1; i <= n; i++) { int u, v, w; cin >> w >> u >> v; hz[i] = w; if(u != 0) { wth[i].push_back(u); wth[u].push_back(i); } if(v != 0) { wth[i].push_back(v); wth[v].push_back(i); } } for(int i = 1; i <= n; i++) { dfs(i, 0, 0, i); ans = min(ans, a[i]); } cout << ans; return 0;}
Plain and Simple Dividing “Word”
// Rerooting DP solution#include <iostream>#include <vector>#include <algorithm>using namespace std;vector <int> wth[105];int ans = 1e9, cnt[105], hz[105];int a[105];void dfs(int now, int f, int dep){ cnt[now] = hz[now]; a[1] += hz[now] * dep; for(auto v : wth[now]) { if(v == f) { continue; } dfs(v, now, dep + 1); cnt[now] += cnt[v]; }}void dfs2(int u, int f){ if(u != 1) { a[u] = a[f] + (cnt[1] - cnt[u]) - cnt[u]; } ans = min(ans, a[u]); for(auto v : wth[u]) { if(v == f) { continue; } dfs2(v, u); }}int main(){ int n; cin >> n; for(int i = 1; i <= n; i++) { int u, v, w; cin >> w >> u >> v; hz[i] = w; if(u != 0) { wth[i].push_back(u); wth[u].push_back(i); } if(v != 0) { wth[i].push_back(v); wth[v].push_back(i); } } dfs(1, 0, 0); dfs2(1, 0); cout << ans; return 0;}
This is my first time writing a solution. If there are any inaccuracies, please feel free to point them out =D