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 }

 

posted @ 2022-06-24 18:28  YHXo  阅读(22)  评论(0编辑  收藏  举报