HDU 2196 Computer (树上最长路)树形DP
Posted 00isok
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 2196 Computer (树上最长路)树形DP相关的知识,希望对你有一定的参考价值。
<题目链接>
题目大意:
输出树上每个点到其它点的最大距离。
解题分析:
下面的做法是将树看成有向图的做法,计算最长路需要考虑几种情况。
dp[i][0] : 表示以i为根的子树中的结点与i的最大距离
dp[i][1] : 表示以i为根的子树中的结点与u的次大距离
dp[i][2] : 表示i往父亲节点方向走的最大距离
第一就是点 i 在以点 i 为根的子树中的最长距离,这个可以直接在点 i 的子树中求得;
第二就是点 i 朝父亲节点方向的最长距离,这个距离分为三种:
1) 点 i 在以 fa 为根的子树中的最长路径上,这时的它朝fa 的最长距离(但是不超过fa的子树继续向上,即只在fa的子树的其它分支进行操作)为 cost<u,fa> + 以fa 为根的子树中的次长路;
2)点 i 不在以fa 为根的子树的最长路径上,这时它朝 fa 的最长距离为(但是不超过fa 的子树继续向上,即只在fa的子树的其它分支进行操作), cost<u,fa> + fa 子树中的最长路;
3)点 i 向 fa 的 fa 的子树进行扩展比较,所以需要和dp[fa][2] 比较。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 6 const int N = 1e4 +10; 7 int dp[N][5]; 8 struct Node{ 9 int to,next,cost; 10 }edge[N]; 11 12 int n,cnt,head[N]; 13 void init(){ 14 cnt=0; 15 memset(head,-1,sizeof(head)); 16 } 17 void addedge(int u,int v,int w){ 18 edge[cnt].to=v,edge[cnt].cost=w,edge[cnt].next=head[u]; 19 head[u]=cnt++; 20 } 21 void dfs1(int u){ 22 int ans1=0,ans2=0; 23 for(int i=head[u];~i;i=edge[i].next){ 24 int v=edge[i].to,cost=edge[i].cost; 25 dfs1(v); 26 int res=dp[v][0]+cost; 27 if(res>=ans1){ 28 ans2=ans1; //ans1记录最长路,ans2记录次长路 29 ans1=res; 30 }else if(res>ans2) ans2=res; 31 } 32 dp[u][0]=ans1; //dp[u][0]为以u为根的子树的最长路 33 dp[u][1]=ans2; //dp[u][1]为以u为根的子树的次长路 34 } 35 void dfs2(int fa){ 36 for(int i=head[fa];~i;i=edge[i].next){ 37 int v=edge[i].to,cost=edge[i].cost; 38 dp[v][2]=max(dp[fa][2],dp[v][0]+cost == dp[fa][0]? dp[fa][1]:dp[fa][0])+cost; 39 //dp[fa][2]表示向父亲方向走的最长路; 按v是否在以fa为根的子树中的最长路径上分类讨论,dp[v][2]有两种选择 40 //相当于,上面的式子考虑了v向fa方向走最长路的三种情况 41 dfs2(v); 42 } 43 } 44 int main(){ 45 while(~scanf("%d",&n)){ 46 init(); 47 for(int i=2;i<=n;i++){ 48 int u,w;scanf("%d%d",&u,&w); 49 addedge(u,i,w); 50 } 51 dfs1(1);dfs2(1); 52 for(int i=1;i<=n;i++){ 53 printf("%d ",max(dp[i][0],dp[i][2])); //以i为根的最长路;向父亲方向走的最长路 54 } 55 } 56 }
2019-02-03
以上是关于HDU 2196 Computer (树上最长路)树形DP的主要内容,如果未能解决你的问题,请参考以下文章