「HDU 2196」题解
Description
Link
给定一棵树,求树上每个点到树上其他点的距离最大值。
其中 \(1\leq n\leq10^4\)。
Solution
经典的换根 DP。
首先我们可以明确每个点有两种方式走出去:
- 到子节点中的一个。
- 到父节点的其他子节点或父节点以上的节点的子节点。
考虑 DFS 求出每个点到其子节点的距离最大值,称这个值为 \(dp[i][1]\),这是第一种情况。
同时记录每个点到其子节点的距离最次大值,称这个值为 \(dp[i][0]\)。
设 \(ans[i]\) 为 i 通过第二种情况走到的最大距离。
则:
\(res[i]=\max(dp[i],ans[fa[i]]+dis(i,fa[i]))\)
考虑 \(ans[i]\) 的计算。
- \(ans[i]=ans[fa[i]]+dis(i,fa[i])\)
- \(ans[i]=dp[fa[i]][1]+dis(i,fa[i]) (dp[fa[i]]\neq dp[i][1]+dis(i,fa[i]))\)
- \(ans[i]=dp[fa[i]][0]+dis(i,fa[i])\)
三种方案分类讨论即可。
Code:
#include<cstdio>
#include<iostream>
#include<vector>
using namespace std;
int n,dp[10005][2],ans[10005];
struct ren{
int to,val;
ren(){};
ren(int T,int V)
{
to=T;
val=V;
}
};
vector<ren> v[10005];
void dfs(int now,int fa)
{
dp[now][1]=dp[now][0]=0;
for(int i=0;i<v[now].size();i++){
int p=v[now][i].to,z=v[now][i].val;
if(p==fa){
continue;
}
dfs(p,now);
if(dp[now][1]<dp[p][1]+z){
dp[now][0]=max(dp[now][1],dp[now][0]);
dp[now][1]=dp[p][1]+z;
}
else{
if(dp[p][1]+z>dp[now][0])
{
dp[now][0]=dp[p][1]+z;
}
}
}
}
void DP(int now,int fa){
for(int i=0;i<v[now].size();i++){
int p=v[now][i].to,z=v[now][i].val;
if(p==fa){
continue;
}
if(dp[now][1]==dp[p][1]+z)
{
ans[p]=max(ans[now],dp[now][0])+z;
}
else{
ans[p]=max(ans[now],dp[now][1])+z;
}
DP(p,now);
}
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
for(int i=1;i<=n;i++)
{
ans[i]=dp[i][0]=dp[i][1]=0;
v[i].clear();
}
for(int i=2;i<=n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
v[i].push_back((ren){x,y});
v[x].push_back((ren){i,y});
}
dfs(1,-1);
DP(1,-1);
for(int i=1;i<=n;i++)
{
printf("%d\n",max(ans[i],dp[i][1]));
}
}
return 0;
}
\(\Bbb{End.}\)
\(\Bbb{Thanks}\) \(\Bbb{For}\) \(\Bbb{Reading.}\)
本文来自博客园,作者:{StranGePants},转载请注明原文链接:https://www.cnblogs.com/StranGePants/p/15154513.html