📺 📺 📺
题意:求与每个点距离最远的点的距离
选择一个根,求出他向下和向上分别的最大值,两者再求一个最大值即可。
这里的DP也可以用在求直径上(树中存在负权的时候dfs/bfs不再适用), 把最后一步换成dp0与dp2求和即可
int n;
int id[MX];//i结点的最深链在哪个儿子
ll dp[MX][3];
int head[MX],tot;
struct IN{int v,w,nxt;}edge[MX<<1];
void add(int u,int v,int w)
{
edge[tot].v=v;edge[tot].w=w,edge[tot].nxt=head[u];
head[u]=tot++;
}
void dfs1(int x,int fx)
{
int mx0=0,mx1=0;
for(int i=head[x];i!=-1;i=edge[i].nxt)
{
int v=edge[i].v;
if(v==fx) continue;
dfs1(v,x);
if(dp[v][0]+edge[i].w>=mx0) mx1=mx0,mx0=dp[v][0]+edge[i].w,id[x]=v;
else if(dp[v][0]+edge[i].w>mx1) mx1=dp[v][0]+edge[i].w;
}
dp[x][0]=mx0,dp[x][1]=mx1;
}
void dfs2(int x,int fx)
{
for(int i=head[x];i!=-1;i=edge[i].nxt)
{
int v=edge[i].v;
if(v==fx) continue;
if(v==id[x]) dp[v][2]=edge[i].w+max(dp[x][1],dp[x][2]);
else dp[v][2]=edge[i].w+max(dp[x][0],dp[x][2]);
dfs2(v,x);
}
}
signed main()
{
while(cin>>n)
{
memset(head,-1,sizeof(head));
memset(dp,0,sizeof(dp));
tot=0;
for(int u=2;u<=n;++u)
{
int v,w;cin>>v>>w;
add(u,v,w);add(v,u,w);
}
dfs1(1,0);
dfs2(1,0);
rpp(i,n) cout<<max(dp[i][0],dp[i][2])<<endl;
}
stop;
}