题目含义
找出每台电脑距离最远电脑的长度
题目分析
对于节点v来说,如果最长长度在它的子树里,我们取dp[u][0]
否则,最长长度要经过它的父节点u,v的最长长度=dis(u,v)+u的最长长度
第一种情况,如果u的最长长度经过v这个子节点,那么很明显最长长度不可取,那我们就要去第二长长度dp[u][1]
第二种情况,如果u的最长长度不经过v这个子节点,那么就取u的最长长度dp[u][0]
所以每一个节点,都要求子树最长距离dp[u][0],第二长距离dp[u][1]
为了计算方便,还要求经过父节点的最长距离dp[u][2]
更详细的过程可以看这个博主的博客
题目代码
#include<stdio.h> #include<iostream> #include<string.h> using namespace std; const int maxn=1e4+7; int n,q,a,b,c,tot; int head[maxn],dp[maxn][3],longest[maxn]; struct node{ int to,w,next; }edge[maxn*2]; void add(int u,int v,int w){ edge[tot].to=v; edge[tot].w=w; edge[tot].next=head[u]; head[u]=tot++; } int dfs1(int u,int fa){ if(dp[u][0]>=0)return dp[u][0]; dp[u][0]=dp[u][1]=dp[u][2]=longest[u]=0; for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].to; if(v==fa)continue; if(dp[u][0]<dfs1(v,u)+edge[i].w){ dp[u][1]=dp[u][0]; dp[u][0]=dfs1(v,u)+edge[i].w; longest[u]=v; } else if(dp[u][1]<dfs1(v,u)+edge[i].w){ dp[u][1]=dfs1(v,u)+edge[i].w; } } return dp[u][0]; } void dfs2(int u,int fa){ for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].to; if(v==fa)continue; if(v==longest[u])dp[v][2]=max(dp[u][1],dp[u][2])+edge[i].w; else dp[v][2]=max(dp[u][0],dp[u][2])+edge[i].w; dfs2(v,u); } } int main(){ while(~scanf("%d",&n)){ tot=0; memset(head,-1,sizeof(head)); memset(dp,-1,sizeof(dp)); memset(longest,-1,sizeof(longest)); for(int i=2;i<=n;i++){ scanf("%d%d",&a,&b); add(a,i,b)/*,add(i,a,b)*/; } dfs1(1,0); dfs2(1,0); for(int i=1;i<=n;i++) printf("%d\n",max(dp[i][0],dp[i][2])); } return 0; }