题目要求:求树上每个点能到达的最远距离
dp[u][0]:u的子树下u的最远距离是多少
dp[u][1]:u的子树次远距离是多少
dp[u][2]:u的父亲能走的最远距离是多少
dp[0] [1]dfs处理即可
如果vi不是u最长距离经过的节点,f[vi][1] = dist(vi,u)+max(f[u][0], f[u][1])
如果vi是u最长距离经过的节点,那么不能选择f[u][0],因为这保存的就是最长距离,要选择u次大距离
#include<bits/stdc++.h> #define mem(a,b) memset(a,b,sizeof(a)) using namespace std; const int maxn=1e5+10; struct edge{ int u,v,w,next; }e[maxn]; int g[maxn],tot=0; int dp[maxn][3]; void creat_edge(int u,int v,int w) { e[++tot]=(edge){u,v,w,g[u]}; g[u]=tot; } void dfs(int u)//递归求得u子树中的最大与次大 0最大 1次大 { for(int i=g[u];i>0;i=e[i].next) { int v=e[i].v; dfs(v); int w=e[i].w; int temp= dp[v][0]+w; if(temp>=dp[u][0]) { dp[u][1]=dp[u][0]; dp[u][0]=temp; } else if(temp>dp[u][1]) dp[u][1]=temp; } } void dfs1(int u) { for(int i=g[u];i>0;i=e[i].next) { int v=e[i].v,w=e[i].w; if(dp[u][0]==dp[v][0]+w)//如果当前节点在最大路径上 只能取次大路径 dp[v][2]=max(dp[u][2],dp[u][1])+w; else dp[v][2]=max(dp[u][2],dp[u][0])+w; dfs1(v); } } int main() { int n; while(~scanf("%d",&n)) { mem(g,0); mem(dp,0); for(int i=2;i<=n;i++) { int u=i,v,w; scanf("%d%d",&v,&w); creat_edge(v,u,w); // creat_edge(v,u,w); } dfs(1); dfs1(1); for(int i=1;i<=n;i++) cout<<max(dp[i][0],dp[i][2])<<" "; } return 0; }