HDU2196 Computer (树形DP-换根)
dp[u][0]表示u向下走的最大距离;
dp[u][1]表示u向下走的次大距离;
dp[u][2]表示u向上走的最大距离;
最后的答案就是每个点的max(dp[u][0],dp[u][2]);
求解次大距离并记录idx在求解向上最大距离中是有必要的,可以画图分析。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int MAXN=10000+10; 6 int dp[MAXN][3]; 7 int idx[MAXN];//用来记录u往下的最大距离经过哪个子节点 8 struct Edge{ 9 int v,w,next; 10 }edge[MAXN<<1]; 11 int cnt,head[MAXN]; 12 13 void add(int u,int v,int w){ 14 edge[cnt].v=v; 15 edge[cnt].w=w; 16 edge[cnt].next=head[u]; 17 head[u]=cnt++; 18 } 19 20 void dfs1(int u,int fa){ 21 int mx1=0,mx2=0; 22 for(int i=head[u];~i;i=edge[i].next){ 23 int v=edge[i].v; 24 if(v==fa) continue; 25 dfs1(v,u); 26 int c=dp[v][0]+edge[i].w; 27 if(mx1<=c) mx2=mx1,mx1=c,idx[u]=v; 28 else if(mx2<c) mx2=c; 29 } 30 dp[u][0]=mx1;//向下走的最大值 31 dp[u][1]=mx2;//向下走的次大值 32 } 33 34 void dfs2(int u,int fa){//求u向上可以走的最大值 35 for(int i=head[u];~i;i=edge[i].next){ 36 int v=edge[i].v; 37 if(v==fa) continue; 38 if(idx[u]==v) 39 dp[v][2]=max(dp[u][1],dp[u][2])+edge[i].w; 40 else 41 dp[v][2]=max(dp[u][0],dp[u][2])+edge[i].w; 42 dfs2(v,u); 43 } 44 } 45 46 int main(){ 47 int n,a,b; 48 while(~scanf("%d",&n)){ 49 cnt=0; 50 memset(head,-1,sizeof(head)); 51 for(int i=2;i<=n;i++){ 52 scanf("%d%d",&a,&b); 53 add(i,a,b);add(a,i,b); 54 } 55 memset(dp,0,sizeof(dp)); 56 dfs1(1,1); 57 dfs2(1,1); 58 for(int i=1;i<=n;i++) 59 printf("%d\n",max(dp[i][0],dp[i][2])); 60 } 61 return 0; 62 }