@Acqua
2019-01-25T02:07:21.000000Z
字数 1308
阅读 988
动态规划
给定一棵个节点的树和边权,求每个节点与其距离最远的点的距离。
遍,第一遍自下向上更新,求出以为根的子树中与相距最远距离和次远距离,记为、。
第二遍自上向下更新,求出通过其与父节点连边达到的最远距离,记为。
若记录的最远距离所属的路径通过,那么如果
。
// La Pluie#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const int N=10005;struct edge{int v,w,next;}e[N<<1];int head[N],n,k,dp[N][3];// dp[u][0]: 以 u 为根的子树内 u 的最大距离// dp[u][1]: 以 u 为根的子树内 u 的次大距离// dp[u][2]: u 通过其父亲能达到的最大距离void adde(int u,int v,int w){e[k]=(edge){v,w,head[u]};head[u]=k++;}void dfs(int u,int f){for(int i=head[u];i!=-1;i=e[i].next){int v=e[i].v;if(v==f) continue;dfs(v,u);int pluie=dp[v][0]+e[i].w;if(pluie>dp[u][0]){dp[u][1]=dp[u][0];dp[u][0]=pluie;}else if(pluie>dp[u][1]){dp[u][1]=pluie;}}}void Dfs(int u,int f){for(int i=head[u];i!=-1;i=e[i].next){int v=e[i].v;if(v==f) continue;if(dp[u][0]==dp[v][0]+e[i].w){dp[v][2]=max(dp[u][2],dp[u][1])+e[i].w;}else{dp[v][2]=max(dp[u][2],dp[u][0])+e[i].w;}Dfs(v,u);}}int main(){while(~scanf("%d",&n)){memset(head,-1,sizeof(head));memset(dp,0,sizeof(dp));k=1;for(int v=2;v<=n;v++){int u,w;scanf("%d%d",&u,&w);adde(u,v,w);adde(v,u,w);}dfs(1,0);Dfs(1,0);for(int i=1;i<=n;i++){printf("%d\n",max(dp[i][0],dp[i][2]));}}return 0;}