求出每一点到所有点的最大距离,刚开始就有点想法求最长边的问题,但想了一会不知道怎么去把子节点转化成根节点。
任选一点为根节点,先求出每个节点到子节点的最大距离和次大距离,然后更新每个子节点的最大,次大距离,就是把每个子节点当一次根节点,如果它在父节点的最大距离边上,就用次大距离+到父节点的距离与自己的最大次大距离比较,,,,
#include<stdio.h>
#include<string.h>
#define N 10001
int n,head[N],num,vis[N],dp[N][2];
struct edge
{
int st,ed,next,w;
}E[N*2];
void addedge(int x,int y,int w)
{
E[num].st=x;
E[num].ed=y;
E[num].w=w;
E[num].next=head[x];
head[x]=num++;
}
int dfs(int u)
{
int i,v;
vis[u]=1;
for(i=head[u];i!=-1;i=E[i].next)
{
v=E[i].ed;
if(vis[v]==1)continue;
int temp=dfs(v)+E[i].w;
if(temp>dp[u][1])//最长边
{
dp[u][0]=dp[u][1];
dp[u][1]=temp;
}
else if(temp>dp[u][0])//次长边
{
dp[u][0]=temp;
}
}
return dp[u][1];
}
void dfs1(int u)
{
vis[u]=1;
int i,v,temp;
for(i=head[u];i!=-1;i=E[i].next)
{
v=E[i].ed;
if(vis[v]==1)continue;
if(dp[v][1]+E[i].w==dp[u][1])//如果改点在父节点的最长边上,就与次长边比较
temp=dp[u][0]+E[i].w;
else temp=dp[u][1]+E[i].w;//不在父节点的最长边上,就与最长边比较
if(temp>dp[v][1])
{
dp[v][0]=dp[v][1];
dp[v][1]=temp;
}
else if(temp>dp[v][0])
{
dp[v][0]=temp;
}
dfs1(v);
}
}
int main()
{
int i,x,y,w;
while(scanf("%d",&n)!=-1)
{
memset(head,-1,sizeof(head));
num=0;
for(x=2;x<=n;x++)
{
scanf("%d%d",&y,&w);
addedge(x,y,w);
addedge(y,x,w);
}
memset(dp,0,sizeof(dp));
memset(vis,0,sizeof(vis));
dfs(1);
memset(vis,0,sizeof(vis));
dfs1(1);
for(i=1;i<=n;i++)
printf("%d\n",dp[i][0]>dp[i][1]?dp[i][0]:dp[i][1]);
}
return 0;
}