持续强化dp中……
Computer
Hint: the example input is corresponding to this graph. And from the graph, you can see that the computer 4 is farthest one from 1, so S1 = 3. Computer 4 and 5 are the farthest ones from 2, so S2 = 2. Computer 5 is the farthest one from 3, so S3 = 3. we also get S4 = 4, S5 = 4.
5 1 1 2 1 3 1 1 1
3 2 3 4 4
这次找了一道典型的树形dp。求一个树中所有节点能到达的最远距离。需要用2个dfs。首先第一个dfs求出每个节点i在其子树中的正向最大距离(dp[i][0])和正向次大距离(dp[i][1])。因此还要标记节点i在其子树中的最大距离经过了节点j(即j是i的一个儿子)。我们可以知道建立的这棵树,i节点的最远距离只有两种选择:i节点所在子树的最大距离,或者i节点连接它的父节点所能到达的最大距离。所以我们只要求出反向最大距离(即i节点往它的父节点走所能到达的最大距离)(dp[i][2])就可以知道i节点在整个树中能走的最大距离了。反向最大距离求法:i节点往它的父节j点走,如果它的父节点的正向最大距离不经过i的话,那么反向最大距离就是它父节点的max(正向最大距离,反向最大距离)+len[i][j],否则就是它父节点的max(正向次大距离,反向最大距离)+ len[i][j]。ans=max(dp[i][0],dp[i][2])。
Code:
#include<bits/stdc++.h>
#define N 100005
using namespace std;
int tot,dp[N][3],head[2*N],id[N];
struct edge
{
int vet,next,len;
}edge[N*2];
inline int read()
{
int f=1,x=0;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
x*=f;
return x;
}
void add(int x,int y,int len)
{
edge[++tot].vet=y;
edge[tot].next=head[x];
head[x]=tot;
edge[tot].len=len;
}
void dfs1(int u,int father)
{
for(int i=head[u];i;i=edge[i].next)
{
int v=edge[i].vet;
if(v==father)continue;
dfs1(v,u);
if(dp[u][0]<dp[v][0]+edge[i].len)
{
id[u]=v;
dp[u][1]=max(dp[u][1],dp[u][0]);
dp[u][0]=dp[v][0]+edge[i].len;
}else dp[u][1]=max(dp[u][1],dp[v][0]+edge[i].len);
}
}
void dfs2(int u,int father)
{
for(int i=head[u];i;i=edge[i].next)
{
int v=edge[i].vet;
if(v==father)continue;
if(v==id[u])dp[v][2]=max(dp[u][2],dp[u][1])+edge[i].len;else
dp[v][2]=max(dp[u][2],dp[u][0])+edge[i].len;
dfs2(v,u);
}
}
int main()
{
int n;
while(~scanf("%d",&n))
{
tot=0;
memset(dp,0,sizeof(dp));
memset(head,0,sizeof(head));
for(int i=1;i<=n-1;i++)
{
int x=read(),y=read();
add(i+1,x,y);add(x,i+1,y);
}
dfs1(1,-1);
dfs2(1,-1);
for(int i=1;i<=n;i++)
printf("%d\n",max(dp[i][0],dp[i][2]));
}
return 0;
}