??求树上每个点到其他点的最大距离。
??首先随便选择一个顶点作为根然后跑一遍dfs,记录每个顶点以其为根能到达的最大深度和次大深度,然后再跑一遍dfs,对于每个顶点,如果要到达一个距离最大的点,要么就是原来中的子树中的距离最大的点,要么就是经过父节点的某个点。
const int maxn = 1e4+10;
const int maxm = 1e6+10;
vector<int> e[maxn];
int n, w[maxn], son[maxn];
ll dp[maxn][3]; /*dp[u][0]是原子树中距离u最远的距离,
son[v]是距离u最远的顶点,dp[u][1]是次元距离,dp[u][2]是经过父节点的最远距离*/
void dfs1(int u) {
for (auto v : e[u]) {
dfs1(v);
ll len = dp[v][0]+w[v]; int t = v;
if (dp[u][0]<len) {
swap(len, dp[u][0]);
swap(t, son[u]);
}
if (dp[u][1]<len) dp[u][1] = len;
}
}
void dfs2(int u) {
for (auto v : e[u]) {
if (son[u]==v) dp[v][2] = max(dp[u][1], dp[u][2])+w[v];
else dp[v][2] = max(dp[u][0], dp[u][2])+w[v];
dfs2(v);
}
}
void init() {
for (int i = 0; i<=n; ++i) {
e[i].clear();
dp[i][0] = dp[i][1] = dp[i][2] = 0;
}
}
int main() {
while(cin >> n) {
init();
for (int i = 2, a; i<=n; ++i) {
cin >> a >> w[i];
e[a].push_back(i);
}
dfs1(1); dfs2(1);
for (int i = 1; i<=n; ++i) cout << max(dp[i][0], dp[i][2]) << endl;
}
return 0;
}
HDU - 2196 Computer(二次扫描+换根法树形dp)
原文:https://www.cnblogs.com/shuitiangong/p/14608315.html