zoukankan      html  css  js  c++  java
  • HDU 2196 Computer (树上最长路)【树形DP】

    <题目链接>

    题目大意:

    输出树上每个点到其它点的最大距离。

    解题分析:

    下面的做法是将树看成有向图的做法,计算最长路需要考虑几种情况。

    dp[i][0] : 表示以i为根的子树中的结点与i的最大距离

    dp[i][1] : 表示以i为根的子树中的结点与i的次大距离

    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

  • 相关阅读:
    C语言网 蓝桥杯 1117K-进制数
    C语言网蓝桥杯1116 IP判断
    LeetCode 面试题14- II. 剪绳子 II
    LeetCode 面试题06. 从尾到头打印链表
    LeetCode 面试题05. 替换空格
    LeetCode 面试题04. 二维数组中的查找
    LeetCode 面试题03. 数组中重复的数字
    LeetCode 3. 无重复字符的最长子串
    LeetCode 202. 快乐数
    LeetCode 154. 寻找旋转排序数组中的最小值 II
  • 原文地址:https://www.cnblogs.com/00isok/p/10349885.html
Copyright © 2011-2022 走看看