HDU 2196 Computer
HDU 2196 Computer
题意:求每个节点能到达的最远距离。
题解:
设$ dp[u][0] $ 节点u走子树能到达的最大距离。
\(dp[u][1]\) 节点u走子树能到达的次大距离。(这里的次大值不是真正意义上的次大值,而是与最大值不走同一个儿子节点的次大值)
\(dp[u][2]\) 节点u第一步走父亲节点能走的最大距离。
如果这三个值你都知道那么答案就简单了 \(ans = max(dp[u][0], dp[u][2])\)
先说下前两个怎么求。
\(dp[u][0] = max(dp[to][0] + cost, dp[u][0])\) 其中 cost为边权, to 为u的儿子节点
最大值求出来次大值就很简单了
具体看代码:
void dfs(int u, int fa){
for(auto it: g[u]){
ll cost = it.second;
int to = it.first;
if(to == fa)continue;
dfs(to, u);
if(dp[u][0] < dp[to][0] + cost){ // 更新最大值
dp[u][1] = dp[u][0]; // 更新次大值
dp[u][0] = dp[to][0] + cost;
}else if(dp[u][1] < dp[to][0] + cost){
dp[u][1] = dp[to][0] + cost; // 更新次大值
}
}
}
求出了\(dp[u][0]\) 与 \(dp[u][1]\) 接下来就是求 \(dp[u][3]\)
我们设 fa 为 u 的父亲节点。
假设我们的 u 是根节点的儿子节点(也就是 节点1的儿子节点)
\(if(dp[u][0] + cost) == dp[fa][0])\) (cost 为fa 到 u的边权)如果这个条件成立,说明 \(dp[fa][0]\) 是儿子为 \(u\) 的节点 转移的, 那么 \(dp[fa][3]\) 肯定有 \(dp[fa][2]\) 转移了
如果不成立 就是又 \(dp[u][0]\)转移了
那1好节点的孙子子节点也就是由儿子节点的第一步走父亲节点状态和儿子节点取最大值或次大值的状态中取最优的, 后面也就以此类推。
具体看代码:
void dfs1(int u, int fa){
for(auto it: g[u]){
int to = it.first;
ll cost = it.second;
if(to == fa)continue;
if(dp[to][0] + cost == dp[u][0]){
dp[to][2] = max(dp[u][2] + cost, dp[u][1] + cost); // 选次大值
}else{
dp[to][2] = max(dp[u][2] + cost, dp[u][0] + cost); // 选最大值
}
}
for(auto it: g[u]){
int to = it.first;
if(to == fa)continue;
dfs1(to, u);
}
}
ac代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 7;
typedef long long ll;
vector<pair<int, ll> >g[N];
ll dp[N][3];
void dfs(int u, int fa){
for(auto it: g[u]){
ll cost = it.second;
int to = it.first;
if(to == fa)continue;
dfs(to, u);
if(dp[u][0] < dp[to][0] + cost){ // 更新最大值
dp[u][1] = dp[u][0]; // 更新次大值
dp[u][0] = dp[to][0] + cost;
}else if(dp[u][1] < dp[to][0] + cost){
dp[u][1] = dp[to][0] + cost; // 更新次大值
}
}
}
void dfs1(int u, int fa){
for(auto it: g[u]){
int to = it.first;
ll cost = it.second;
if(to == fa)continue;
if(dp[to][0] + cost == dp[u][0]){
dp[to][2] = max(dp[u][2] + cost, dp[u][1] + cost); // 选次大值
}else{
dp[to][2] = max(dp[u][2] + cost, dp[u][0] + cost); // 选最大值
}
}
for(auto it: g[u]){
int to = it.first;
if(to == fa)continue;
dfs1(to, u);
}
}
int main(){
int n;
while(~scanf("%d", &n)){
for(int i = 0; i <= n; i++)g[i].clear();
memset(dp, 0, sizeof(dp));
for(int i = 2; i <= n; i++){
int u; ll w;
scanf("%d %lld", &u, &w);
g[u].push_back({i, w});
g[i].push_back({u, w});
}
dfs(1, 0);
dfs1(1, 0);
for(int i = 1; i <= n; i++){
printf("%lld\n", max(dp[i][2], dp[i][0]));
}
}
}