题意:给你一个树,求出所有节点在树中能到达的点的最远距离;
分析:dp[i][0],表示顶点为i的子树的,距顶点i的最长距离;dp[i][1],表示Tree(i的父节点)-Tree(i)的最长距离+i跟i的父节点距离;dp[i][0]通过dfs1可以很快求出;dp[i][1]可以通过父节点转移来,要维护一个最长mx1和经过的子节点v1,次大mx2和子节点v2,更新时如果v是v1,那么只能从mx2转移,否则就是从mx1转移;
#include<bits/stdc++.h>
#define pb push_back
using namespace std;
const int maxn=1e5+7;
bool vis[maxn];
int dp[maxn][2];
struct node{int v,w;};
vector<node> g[maxn];
int n;
int dfs1(int u)
{
vis[u]=1;dp[u][0]=0;
for(auto i:g[u]) if(!vis[i.v]) dp[u][0]=max(dp[u][0],dfs1(i.v)+i.w);
return dp[u][0];
}
void dfs2(int u)
{
vis[u]=1;
int mx1=0,mx2=0,v1,v2;
for(auto i:g[u])
{
if(vis[i.v]) continue;
int kk=dp[i.v][0]+i.w;
if(kk>mx1) {mx2=mx1;v2=v1;mx1=kk;v1=i.v;}
else if(kk==mx1 || kk>mx2) mx2=kk,v2=i.v;
}
if(u!=1)
{
int kk=dp[u][1],v=-1;
if(kk>mx1) {mx2=mx1;v2=v1;mx1=kk;v1=v;}
else if(kk==mx1 || kk>mx2) mx2=kk,v2=v;
}
for(auto i:g[u])
{
if(vis[i.v]) continue;
if(i.v==v1) dp[i.v][1]=mx2+i.w;
else dp[i.v][1]=mx1+i.w;
dfs2(i.v);
}
}
int main()
{
while(~scanf("%d",&n) && n)
{
for(int i=0;i<n;i++) g[i].clear();
for(int u=2;u<=n;u++)
{
int v,w;scanf("%d%d",&v,&w);
g[u].pb({v,w});g[v].pb({u,w});
}
memset(dp,-1,sizeof(dp));
memset(vis,0,sizeof(vis));
dfs1(1);
memset(vis,0,sizeof(vis));
dfs2(1);
for(int i=1;i<=n;i++) printf("%d\n",max(dp[i][0],dp[i][1]));
}
return 0;
}