参考来自http://blog.csdn.net/shuangde800/article/details/9732825的思路:
跟思路中不太相同的是,我们如下设置DP数组:
dp[i][0] : 表示以i为根的子树中的结点与i的最大距离
dp[i][1] : 表示以i为根的子树中的结点与u的次大距离(即上述思路中的secondDist)
dp[i][2] : 表示i往父亲节点方向走的最大距离
同样的,我们也做两次DFS,但是第一次的时候,我们将dp[i][0]和dp[i][1]一起算出来;
第二次DFS就可以直接用dp[i][0]和dp[i][1]。
代码如下:
1 #include<cstdio> 2 #include<algorithm> 3 #include<vector> 4 #include<cstring> 5 #define MAXN 10000+5 6 using namespace std; 7 //dp[i][0] : 表示以i为根的子树中的结点与i的最大距离 8 //dp[i][1] : 表示以i为根的子树中的结点与u的次大距离 9 //dp[i][2] : 表示i往父亲节点方向走的最大距离 10 int n,dp[MAXN][3],idx[MAXN]; 11 struct Edge{ 12 int u,v,w; 13 }; 14 vector<Edge> child[MAXN]; 15 void dfs1(int now) 16 { 17 if(child[now].size()==0) 18 { 19 dp[now][0]=0; 20 dp[now][1]=0; 21 return; 22 } 23 for(int i=0;i<child[now].size();i++) 24 { 25 Edge edge=child[now][i]; 26 int next=edge.v; 27 dfs1(next); 28 if(dp[now][0] < dp[next][0]+edge.w) // ( "其某个孩子的最大"+"其与孩子的距离" ) > "最大" > "次大" 29 { 30 dp[now][1] = dp[now][0]; 31 dp[now][0] = dp[next][0] + edge.w; 32 idx[now]=next; 33 } 34 else if(dp[now][1] < dp[next][0]+edge.w) // "最大" > ( "其某个孩子的最大"+"其与孩子的距离" ) > "次大" 35 { 36 dp[now][1] = dp[next][0]+edge.w; 37 } 38 } 39 } 40 void dfs2(int now) 41 { 42 for(int i=0;i<child[now].size();i++) 43 { 44 Edge edge=child[now][i]; 45 int next=edge.v; 46 if(idx[now]==next) dp[next][2] = edge.w + max(dp[now][1],dp[now][2]); 47 else dp[next][2] = edge.w + max(dp[now][0],dp[now][2]); 48 dfs2(next); 49 } 50 } 51 int main() 52 { 53 while(scanf("%d",&n)!=EOF) 54 { 55 for(int i=0;i<=MAXN;i++) child[i].clear(); 56 memset(dp,0,sizeof(dp)); 57 memset(idx,0,sizeof(idx)); 58 for(int i=2;i<=n;i++) 59 { 60 int father,length; 61 scanf("%d%d",&father,&length); 62 child[father].push_back((Edge){father,i,length}); 63 } 64 dfs1(1); 65 dfs2(1); 66 for(int i=1;i<=n;i++) 67 { 68 printf("%d\n",max(dp[i][0],dp[i][2])); 69 } 70 } 71 }
总的来说,这是一道很不错的树形DP题。
时间: 2024-10-10 06:52:50